Merge changes I8293baab,I63e248bd
authorEd Warnicke <eaw@cisco.com>
Fri, 16 Aug 2013 12:41:08 +0000 (12:41 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 16 Aug 2013 12:41:08 +0000 (12:41 +0000)
* changes:
  Added sample provider and consumer for MD SAL
  Clean up of binding broker implementation

61 files changed:
opendaylight/clustering/services_implementation/pom.xml
opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml
opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/LoggingListener.java
opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/SimpleClient.java
opendaylight/configuration/integrationtest/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationIT.java
opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/Activator.java
opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java
opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/scheme/AbstractScheme.java
opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml
opendaylight/forwardingrulesmanager/integrationtest/src/test/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerIT.java
opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java
opendaylight/hosttracker/integrationtest/src/test/java/org/opendaylight/controller/hosttracker/internal/HostTrackerIT.java
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/utils/NorthboundUtils.java
opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java
opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java
opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthbound.java
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java
opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ICMP.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NetUtils.java
opendaylight/switchmanager/implementation/pom.xml
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/Activator.java
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java
opendaylight/switchmanager/integrationtest/src/test/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerIT.java
opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java
opendaylight/web/devices/src/main/resources/js/page.js
opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java
opendaylight/web/flows/src/main/resources/js/page.js
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebUtil.java
opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp
opendaylight/web/root/src/main/resources/css/fuelux-responsive.min.css [new file with mode: 0755]
opendaylight/web/root/src/main/resources/css/fuelux.min.css [new file with mode: 0755]
opendaylight/web/root/src/main/resources/css/opendaylight.css [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/form.png [new file with mode: 0755]
opendaylight/web/root/src/main/resources/img/nextpageleft.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/nextpageright.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/search.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/searchremove.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/sort_down.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/sort_up.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/datasource.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/COPYING [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/fuelux/all.min.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/checkbox.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/combobox.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/datagrid.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/loader.min.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/pillbox.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/radio.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/search.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/select.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/spinner.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/tree.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/util.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/fuelux/wizard.js [new file with mode: 0755]
opendaylight/web/root/src/main/resources/js/lib.js
opendaylight/web/root/src/main/resources/js/underscore-min.js [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/js/page.js

index 1d52c4b0777589bff90468248fefa4e4234ddef7..025fbdfccb503fc5750e8d7d2b2c04364678610d 100644 (file)
@@ -39,6 +39,7 @@
         <instructions>
           <Import-Package>
             org.slf4j,
+            !org.apache.logging.log4j.*,
             !bsh*,
             !net.jcip.*,
             !javax.swing,
     <dependency>
       <groupId>org.infinispan</groupId>
       <artifactId>infinispan-core</artifactId>
-      <version>5.2.3.Final</version>
+      <version>5.3.0.Final</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 16dd579abb83962c63f7c3efb3c21d856b1f5409..e917eea825bf7049e620ce8013bf0ce497bc095c 100644 (file)
   <namedCache name="transactional-type">
     <transaction
         transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup"
-        syncRollbackPhase="false"
-        syncCommitPhase="false"
+        syncRollbackPhase="true"
+        syncCommitPhase="true"
         cacheStopTimeout="30000"
         use1PcForAutoCommitTransactions="false"
         autoCommit="true"
         lockingMode="OPTIMISTIC"
-        useSynchronization="false"
+        useSynchronization="true"
         transactionMode="TRANSACTIONAL"
         />
   </namedCache>
index 4f5d432832b3e7e2734d2f879803a79e51b9bb06..1aef9ce276ea039743cb8ab78a677a93c0aaf951 100644 (file)
@@ -25,10 +25,10 @@ public class LoggingListener implements IGetUpdates<Integer, StringContainer> {
     }
 
     @Override
-    public void entryUpdated(Integer key, StringContainer new_value,
+    public void entryUpdated(Integer key, StringContainer newValue,
             String containerName, String cacheName, boolean originLocal) {
         logger.debug(" Cache entry with key " + key + " modified to value "
-                + new_value + "  in cache " + cacheName);
+                + newValue + "  in cache " + cacheName);
     }
 
     @Override
index f681c35c8c9ea376a3d0399269d798479a296689..60be87b86d4add14a4feaabae6a211c2d34f981b 100644 (file)
@@ -9,6 +9,7 @@
 
 package org.opendaylight.controller.clustering.test.internal;
 
+import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.List;
@@ -268,6 +269,24 @@ public class SimpleClient implements CommandProvider {
         ci.println(cacheName + " is no longer being monitored for updates");
     }
 
+    public void _myController(CommandInterpreter ci) {
+        if (this.icluster == null) {
+            ci.println("\nNo Clustering services available");
+            return;
+        }
+        ci.println("This Controller : " +icluster.getMyAddress().getHostAddress());
+    }
+
+    public void _getClusterNodes(CommandInterpreter ci) {
+        if (this.icluster == null) {
+            ci.println("\nNo Clustering services available");
+            return;
+        }
+        for (InetAddress address : icluster.getClusteredControllers()) {
+            ci.println("\t"+address.getHostAddress());
+        }
+    }
+
     public void _listcaches(CommandInterpreter ci) {
         if (this.icluster == null) {
             ci.println("\nNo Clustering services available");
@@ -441,29 +460,6 @@ public class SimpleClient implements CommandProvider {
         }
     }
 
-    @SuppressWarnings("deprecation") //TODO: remove call to deprecated amIStandby
-    public void _getRole(CommandInterpreter ci) {
-        if (this.icluster == null) {
-            ci.println("\nNo Clustering services available");
-            return;
-        }
-        String role = "Active";
-        if (this.icluster.amIStandby()) {
-            role = "Standby";
-        }
-        ci.println("My role is: " + role);
-    }
-
-    @SuppressWarnings("deprecation") //TODO: remove call to deprecated getActiveAddres
-    public void _getActive(CommandInterpreter ci) {
-        if (this.icluster == null) {
-            ci.println("\nNo Clustering services available");
-            return;
-        }
-        ci.println("Current active address is "
-                + this.icluster.getActiveAddress());
-    }
-
     @SuppressWarnings("deprecation") //TODO: remove use of deprecated listenRoleChange
     public void _listenActive(CommandInterpreter ci) {
         if (this.icluster == null) {
@@ -640,16 +636,12 @@ public class SimpleClient implements CommandProvider {
         help.append("\tunlistenActive   - UNListen to Active updates\n");
         help.append("\tdestroy          - Destroy a cache\n");
         help.append("\tcreate           - Create a cache\n");
-        help.append("\tgetRole          - Tell if active or standby\n");
-        help.append("\tgetActive        - Report the IP address of Active\n");
-        help
-                .append("\tputComplex       - Fill a more complex data structure\n");
-        help
-                .append("\tupdateComplex    - Update the value of a more complex data structure\n");
-        help
-                .append("\tgetLogLevel      - Get the loglevel for the logger specified\n");
-        help
-                .append("\tsetLogLevel      - Set the loglevel for the logger specified\n");
+        help.append("\tmyController     - Print this controller's Cluster identifier\n");
+        help.append("\tgetClusterNodes  - Print all the controllers that make this cluster\n");
+        help.append("\tputComplex       - Fill a more complex data structure\n");
+        help.append("\tupdateComplex    - Update the value of a more complex data structure\n");
+        help.append("\tgetLogLevel      - Get the loglevel for the logger specified\n");
+        help.append("\tsetLogLevel      - Set the loglevel for the logger specified\n");
         return help.toString();
     }
 }
index 17b3414c91e174c168895502a63a4e9c8951eb67..956028b73c09b40029d9ef3a8140bc14d5e4ebca 100644 (file)
@@ -91,10 +91,6 @@ public class ConfigurationIT {
                         "0.4.0-SNAPSHOT"),
                 mavenBundle("org.opendaylight.controller",
                         "containermanager.implementation", "0.4.0-SNAPSHOT"),
-                mavenBundle("org.opendaylight.controller", "switchmanager",
-                        "0.5.0-SNAPSHOT"),
-                mavenBundle("org.opendaylight.controller",
-                        "switchmanager.implementation", "0.4.0-SNAPSHOT"),
                 // needed bundles by configuration
                 mavenBundle("org.opendaylight.controller",
                         "clustering.services", "0.4.0-SNAPSHOT"), // what are
index 5ebbfe2ea8cfb26dd6523b54acc147709b56bf2e..4bee2537656e3ac1ddfda162cd20735939a50a58 100644 (file)
@@ -17,6 +17,7 @@ import java.util.Set;
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 import org.opendaylight.controller.clustering.services.ICoordinatorChangeAware;
+import org.opendaylight.controller.connectionmanager.ConnectionMgmtScheme;
 import org.opendaylight.controller.connectionmanager.IConnectionManager;
 import org.opendaylight.controller.sal.connection.IConnectionListener;
 import org.opendaylight.controller.sal.connection.IConnectionService;
@@ -77,7 +78,9 @@ public class Activator extends ComponentActivatorAbstractBase {
         if (imp.equals(ConnectionManager.class)) {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             Set<String> propSet = new HashSet<String>();
-            propSet.add("connectionmanager.nodeconnections");
+            for (ConnectionMgmtScheme scheme:ConnectionMgmtScheme.values()) {
+                propSet.add("connectionmanager."+scheme.name()+".nodeconnections");
+            }
             props.put("cachenames", propSet);
             props.put("scope", "Global");
 
index c4b7d4fe6cf52b9b517d75c53d596778700528d8..fdba533b5bfa827bf2ccd79bf2f061785d06d597 100644 (file)
@@ -176,9 +176,6 @@ public class ConnectionManager implements IConnectionManager, IConnectionListene
 
     @Override
     public void coordinatorChanged() {
-        AbstractScheme scheme = schemes.get(activeScheme);
-        if (scheme == null) return;
-        scheme.handleClusterViewChanged();
         notifyClusterViewChanged();
     }
 
@@ -202,8 +199,7 @@ public class ConnectionManager implements IConnectionManager, IConnectionListene
 
     @Override
     public void entryCreated(Node key, String cacheName, boolean originLocal) {
-        AbstractScheme scheme = schemes.get(activeScheme);
-        logger.debug("Created : {} cache : {} existingValue : {}", key, cacheName, scheme.getNodeConnections().get(key));
+        if (originLocal) return;
     }
 
     /*
@@ -277,6 +273,9 @@ public class ConnectionManager implements IConnectionManager, IConnectionListene
                         connectionService.notifyNodeDisconnectFromMaster(node);
                         break;
                     case CLUSTER_VIEW_CHANGED:
+                        AbstractScheme scheme = schemes.get(activeScheme);
+                        if (scheme == null) return;
+                        scheme.handleClusterViewChanged();
                         connectionService.notifyClusterViewChanged();
                         break;
                     default:
index a490916da2f6bb65a8e3c2ba288b71f356320386..6b20909a877ce81de268c585c5e309be9fe7e2cf 100644 (file)
@@ -10,6 +10,8 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import javax.transaction.SystemException;
+
 import org.opendaylight.controller.clustering.services.CacheConfigException;
 import org.opendaylight.controller.clustering.services.CacheExistException;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
@@ -82,6 +84,7 @@ public abstract class AbstractScheme {
             }
         }
 
+        boolean retry = false;
         for (InetAddress c : toRemove) {
             log.debug("Removing Controller : {} from the Connections table", c);
             for (Iterator<Node> nodeIterator = nodeConnections.keySet().iterator();nodeIterator.hasNext();) {
@@ -89,23 +92,35 @@ public abstract class AbstractScheme {
                 Set <InetAddress> oldControllers = nodeConnections.get(node);
                 Set <InetAddress> newControllers = new HashSet<InetAddress>(oldControllers);
                 if (newControllers.remove(c)) {
-                    boolean replaced = false;
                     try {
-                        replaced = nodeConnections.replace(node, oldControllers, newControllers);
+                        clusterServices.tbegin();
+                        if (!nodeConnections.replace(node, oldControllers, newControllers)) {
+                            log.debug("Replace Failed for {} ", node.toString());
+                            retry = true;
+                            clusterServices.trollback();
+                            break;
+                        } else {
+                            clusterServices.tcommit();
+                        }
                     } catch (Exception e) {
-                        log.debug("Replace exception : ", e);
-                        replaced = false;
-                    }
-                    if (!replaced) {
+                        log.error("Exception in replacing nodeConnections ", e);
+                        retry = false;
                         try {
-                            Thread.sleep(10);
-                        } catch (InterruptedException e) {
-                        }
-                        handleClusterViewChanged();
+                            clusterServices.trollback();
+                        } catch (Exception e1) {}
+                        break;
                     }
                 }
             }
         }
+        if (retry) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            handleClusterViewChanged();
+        }
     }
 
     public Set<Node> getNodes(InetAddress controller) {
@@ -155,24 +170,30 @@ public abstract class AbstractScheme {
         if (oldControllers != null && oldControllers.contains(controller)) {
             Set<InetAddress> newControllers = new HashSet<InetAddress>(oldControllers);
             if (newControllers.remove(controller)) {
-                if (newControllers.size() > 0) {
-                    boolean replaced = false;
-                    try {
-                    replaced = nodeConnections.replace(node, oldControllers, newControllers);
-                    } catch (Exception e) {
-                        log.debug("Replace exception : ", e);
-                        replaced = false;
-                    }
-                    if (!replaced) {
-                        try {
-                            Thread.sleep(10);
-                        } catch (InterruptedException e) {
+                try {
+                    clusterServices.tbegin();
+                    if (newControllers.size() > 0) {
+                        if (!nodeConnections.replace(node, oldControllers, newControllers)) {
+                            clusterServices.trollback();
+                            try {
+                                Thread.sleep(100);
+                            } catch ( InterruptedException e) {}
+                            return removeNodeFromController(node, controller);
                         }
-                        return removeNodeFromController(node, controller);
+                    } else {
+                        nodeConnections.remove(node);
                     }
-                } else {
-                    nodeConnections.remove(node);
+                    clusterServices.tcommit();
+                } catch (Exception e) {
+                    log.error("Excepion in removing Controller from a Node", e);
+                    try {
+                        clusterServices.trollback();
+                    } catch (Exception e1) {
+                        log.error("Error Rolling back the node Connections Changes ", e);
+                    }
+                    return new Status(StatusCode.INTERNALERROR);
                 }
+
             }
         }
         return new Status(StatusCode.SUCCESS);
@@ -206,34 +227,45 @@ public abstract class AbstractScheme {
         }
         newControllers.add(controller);
 
-        if (nodeConnections.putIfAbsent(node, newControllers) != null) {
-            log.debug("PutIfAbsent failed {} to {}", controller.getHostAddress(), node.toString());
-            /*
-             * This check is needed again to take care of the case where some schemes
-             * would not allow nodes to be connected to multiple controllers.
-             * Hence, if putIfAbsent fails, that means, some other controller is competing
-             * with this controller to take hold of a Node.
-             */
-            if (isConnectionAllowed(node)) {
-                log.debug("Trying to replace old={} with new={} for {} to {}", oldControllers.toString(), newControllers.toString(),
-                        controller.getHostAddress(), node.toString());
-                if (!nodeConnections.replace(node, oldControllers, newControllers)) {
-                    try {
-                        Thread.sleep(10);
-                    } catch (InterruptedException e) {
+        try {
+            clusterServices.tbegin();
+            if (nodeConnections.putIfAbsent(node, newControllers) != null) {
+                log.debug("PutIfAbsent failed {} to {}", controller.getHostAddress(), node.toString());
+                /*
+                 * This check is needed again to take care of the case where some schemes
+                 * would not allow nodes to be connected to multiple controllers.
+                 * Hence, if putIfAbsent fails, that means, some other controller is competing
+                 * with this controller to take hold of a Node.
+                 */
+                if (isConnectionAllowed(node)) {
+                    if (!nodeConnections.replace(node, oldControllers, newControllers)) {
+                        clusterServices.trollback();
+                        try {
+                            Thread.sleep(100);
+                        } catch ( InterruptedException e) {}
+                        log.debug("Replace failed... old={} with new={} for {} to {}", oldControllers.toString(), newControllers.toString(),
+                                controller.getHostAddress(), node.toString());
+                        return putNodeToController(node, controller);
+                    } else {
+                        log.debug("Replace successful old={} with new={} for {} to {}", oldControllers.toString(), newControllers.toString(),
+                                controller.getHostAddress(), node.toString());
                     }
-                    log.debug("Replace failed... old={} with new={} for {} to {}", oldControllers.toString(), newControllers.toString(),
-                            controller.getHostAddress(), node.toString());
-                    return putNodeToController(node, controller);
                 } else {
-                    log.debug("Replace successful old={} with new={} for {} to {}", oldControllers.toString(), newControllers.toString(),
-                            controller.getHostAddress(), node.toString());
+                    clusterServices.trollback();
+                    return new Status(StatusCode.CONFLICT);
                 }
             } else {
-                return new Status(StatusCode.CONFLICT);
+                log.debug("Added {} to {}", controller.getHostAddress(), node.toString());
             }
-        } else {
-            log.debug("Added {} to {}", controller.getHostAddress(), node.toString());
+            clusterServices.tcommit();
+        } catch (Exception e) {
+            log.error("Excepion in adding Controller to a Node", e);
+            try {
+                clusterServices.trollback();
+            } catch (Exception e1) {
+                log.error("Error Rolling back the node Connections Changes ", e);
+            }
+            return new Status(StatusCode.INTERNALERROR);
         }
         return new Status(StatusCode.SUCCESS);
     }
@@ -277,7 +309,7 @@ public abstract class AbstractScheme {
         }
 
         try {
-            clusterServices.createCache("connectionmanager."+name+".nodeconnections", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+            clusterServices.createCache("connectionmanager."+name+".nodeconnections", EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
         } catch (CacheExistException cee) {
             log.error("\nCache already exists - destroy and recreate if needed");
         } catch (CacheConfigException cce) {
index 08dabdeedbd8ea99bebe3f647a4bfdadbed649fc..de0a3bcd19e990c0287338d0b5e3b1fbe8696c1b 100644 (file)
@@ -1,4 +1,4 @@
-<configuration scan="true">
+ <configuration scan="true">
 
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>
       <maxHistory>1</maxHistory>
     </rollingPolicy>
 
+    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+      <maxFileSize>10MB</maxFileSize>
+    </triggeringPolicy>
+
     <encoder>
       <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n</pattern>
     </encoder>
   </appender>
-
+  <appender name="audit-file" class="ch.qos.logback.core.FileAppender">
+        <file>logs/audit.log</file>
+        <append>true</append>
+        <encoder>
+            <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} %msg %n</pattern>
+        </encoder>
+  </appender>
   <root level="error">
     <appender-ref ref="STDOUT" />
     <appender-ref ref="opendaylight.log" />
   </root>
 
   <!--  Base log level  -->
-  <logger name="org.opendaylight" level="INFO"/>
+  <logger name="org.opendaylight.controller" level="INFO"/>
 
   <!-- OSGi logging bridge -->
   <logger name="org.opendaylight.controller.logging.bridge" level="WARN"/>
@@ -55,4 +65,8 @@
   <logger name="org.opendaylight.controller.usermanager" level="INFO"/>
   <!-- Web modules -->
   <logger name="org.opendaylight.controller.web" level="INFO"/>
-</configuration>
+  <!-- additivity=false ensures analytics data only goes to the analytics log -->
+  <logger name="audit" level="INFO" additivity="false">
+       <appender-ref ref="audit-file"/>
+  </logger>
+</configuration>
\ No newline at end of file
index c497eb240a4dba53a4eec1ccd134dc2587231081..6e8d9ab55b3173240567ec818ea9264bef059d77 100644 (file)
@@ -111,11 +111,11 @@ public class ForwardingRulesManagerIT {
                         .versionAsInProject(),
                 mavenBundle("org.opendaylight.controller", "switchmanager")
                         .versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "statisticsmanager").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller",
                         "switchmanager.implementation").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller", "configuration")
                         .versionAsInProject(),
-
                 mavenBundle("org.opendaylight.controller",
                         "configuration.implementation").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller", "hosttracker")
index 3ff474732fe01628996d0c8685b04910080b26e3..4a5259031724853d438c6ed45797bc985ae3e6dc 100644 (file)
@@ -29,6 +29,8 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
 import org.apache.felix.dm.Component;
+import org.eclipse.osgi.framework.console.CommandInterpreter;
+import org.eclipse.osgi.framework.console.CommandProvider;
 import org.opendaylight.controller.clustering.services.CacheConfigException;
 import org.opendaylight.controller.clustering.services.CacheExistException;
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
@@ -63,6 +65,8 @@ import org.opendaylight.controller.switchmanager.ISwitchManagerAware;
 import org.opendaylight.controller.switchmanager.Subnet;
 import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.opendaylight.controller.topologymanager.ITopologyManagerAware;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -80,9 +84,9 @@ import org.slf4j.LoggerFactory;
  */
 
 public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAware, IInventoryListener,
-        ITopologyManagerAware, ICacheUpdateAware<InetAddress, HostNodeConnector> {
-    static final String ACTIVE_HOST_CACHE = "hostTrackerAH";
-    static final String INACTIVE_HOST_CACHE = "hostTrackerIH";
+        ITopologyManagerAware, ICacheUpdateAware<InetAddress, HostNodeConnector>, CommandProvider {
+    static final String ACTIVE_HOST_CACHE = "hosttracker.ActiveHosts";
+    static final String INACTIVE_HOST_CACHE = "hosttracker.InactiveHosts";
     private static final Logger logger = LoggerFactory.getLogger(HostTracker.class);
     private IHostFinder hostFinder;
     private ConcurrentMap<InetAddress, HostNodeConnector> hostsDB;
@@ -130,10 +134,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
             hostTrackerCallable = callable;
         }
     }
-
     // This list contains the hosts for which ARP requests are being sent
     // periodically
-    private final List<ARPPending> ARPPendingList = new ArrayList<HostTracker.ARPPending>();
+    ConcurrentMap<InetAddress, ARPPending> ARPPendingList;
     /*
      * This list below contains the hosts which were initially in ARPPendingList
      * above, but ARP response didn't come from there hosts after multiple
@@ -150,12 +153,13 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
      *
      * We can't recover from condition 3 above
      */
-    private final List<ARPPending> failedARPReqList = new ArrayList<HostTracker.ARPPending>();
+    ConcurrentMap<InetAddress, ARPPending> failedARPReqList;
 
     public HostTracker() {
     }
 
     private void startUp() {
+        nonClusterObjectCreate();
         allocateCache();
         retrieveCache();
 
@@ -213,6 +217,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
     public void nonClusterObjectCreate() {
         hostsDB = new ConcurrentHashMap<InetAddress, HostNodeConnector>();
         inactiveStaticHosts = new ConcurrentHashMap<NodeConnector, HostNodeConnector>();
+        ARPPendingList = new ConcurrentHashMap<InetAddress, ARPPending>();
+        failedARPReqList = new ConcurrentHashMap<InetAddress, ARPPending>();
     }
 
 
@@ -378,26 +384,14 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
 
         arphost.setHostIP(networkAddr);
         arphost.setSent_count((short) 1);
-        ARPPendingList.add(arphost);
+        ARPPendingList.put(networkAddr, arphost);
         logger.debug("Host Added to ARPPending List, IP: {}", networkAddr);
     }
 
-    private void removePendingARPFromList(int index) {
-        if (index >= ARPPendingList.size()) {
-            logger.warn("removePendingARPFromList(): index greater than the List. Size:{}, Index:{}",
-                    ARPPendingList.size(), index);
-            return;
-        }
-        ARPPending arphost = ARPPendingList.remove(index);
-        HostTrackerCallable htCallable = arphost.getHostTrackerCallable();
-        if (htCallable != null)
-            htCallable.wakeup();
-    }
-
     public void setCallableOnPendingARP(InetAddress networkAddr, HostTrackerCallable callable) {
         ARPPending arphost;
-        for (int i = 0; i < ARPPendingList.size(); i++) {
-            arphost = ARPPendingList.get(i);
+        for (Entry <InetAddress, ARPPending> entry : ARPPendingList.entrySet()) {
+            arphost = entry.getValue();
             if (arphost.getHostIP().equals(networkAddr)) {
                 arphost.setHostTrackerCallable(callable);
             }
@@ -407,34 +401,22 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
     private void processPendingARPReqs(InetAddress networkAddr) {
         ARPPending arphost;
 
-        for (int i = 0; i < ARPPendingList.size(); i++) {
-            arphost = ARPPendingList.get(i);
-            if (arphost.getHostIP().equals(networkAddr)) {
-                /*
-                 * An ARP was sent for this host. The address is learned, remove
-                 * the request
-                 */
-                removePendingARPFromList(i);
-                logger.debug("Host Removed from ARPPending List, IP: {}", networkAddr);
-                return;
-            }
+        if ((arphost = ARPPendingList.remove(networkAddr)) != null) {
+            // Remove the arphost from ARPPendingList as it has been learned now
+            logger.debug("Host Removed from ARPPending List, IP: {}", networkAddr);
+            HostTrackerCallable htCallable = arphost.getHostTrackerCallable();
+            if (htCallable != null)
+                htCallable.wakeup();
+            return;
         }
 
         /*
          * It could have been a host from the FailedARPReqList
          */
 
-        for (int i = 0; i < failedARPReqList.size(); i++) {
-            arphost = failedARPReqList.get(i);
-            if (arphost.getHostIP().equals(networkAddr)) {
-                /*
-                 * An ARP was sent for this host. The address is learned, remove
-                 * the request
-                 */
-                failedARPReqList.remove(i);
-                logger.debug("Host Removed from FailedARPReqList List, IP: {}", networkAddr);
-                return;
-            }
+        if  (failedARPReqList.containsKey(networkAddr)) {
+            failedARPReqList.remove(networkAddr);
+            logger.debug("Host Removed from FailedARPReqList List, IP: {}", networkAddr);
         }
     }
 
@@ -784,10 +766,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
     private void updateCurrentHierarchy(Node node, ArrayList<String> currHierarchy, List<List<String>> fullHierarchy) {
         // currHierarchy.add(String.format("%x", currSw.getId()));
         currHierarchy.add(dpidToHostNameHack((Long) node.getID()));
-        ArrayList<String> currHierarchyClone = (ArrayList<String>) currHierarchy.clone(); // Shallow
-                                                                                          // copy
-                                                                                          // as
-                                                                                          // required
+        // Shallow copy as required
+        ArrayList<String> currHierarchyClone = (ArrayList<String>) currHierarchy.clone();
 
         Map<Node, Set<Edge>> ndlinks = topologyManager.getNodeEdges();
         if (ndlinks == null) {
@@ -809,14 +789,27 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
             Node dstNode = lt.getHeadNodeConnector().getNode();
 
             Tier nodeTier = (Tier) switchManager.getNodeProp(node, Tier.TierPropName);
+            /*
+             * If the host is directly attached to the src node, then the node
+             * should have been assigned the "Access" tier in
+             * notifyHostLearnedOrRemoved. If not, it would be assigned
+             * "Unknown" tier. Thus the tier of host attached node cannot be
+             * null. If the src node here, is the next node in the hierarchy of
+             * the nodes, then its tier cannot be null
+             */
+
             Tier dstNodeTier = (Tier) switchManager.getNodeProp(dstNode, Tier.TierPropName);
+            /*
+             * Skip if the tier of the destination node is null
+             */
+            if (dstNodeTier == null) {
+                continue;
+            }
             if (dstNodeTier.getValue() > nodeTier.getValue()) {
                 ArrayList<String> buildHierarchy = currHierarchy;
                 if (currHierarchy.size() > currHierarchyClone.size()) {
-                    buildHierarchy = (ArrayList<String>) currHierarchyClone.clone(); // Shallow
-                                                                                     // copy
-                                                                                     // as
-                                                                                     // required
+                    // Shallow copy as required
+                    buildHierarchy = (ArrayList<String>) currHierarchyClone.clone();
                     fullHierarchy.add(buildHierarchy);
                 }
                 updateCurrentHierarchy(dstNode, buildHierarchy, fullHierarchy);
@@ -899,9 +892,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
     public void subnetNotify(Subnet sub, boolean add) {
         logger.debug("Received subnet notification: {}  add={}", sub, add);
         if (add) {
-            for (int i = 0; i < failedARPReqList.size(); i++) {
+            for (Entry <InetAddress, ARPPending> entry : failedARPReqList.entrySet()) {
                 ARPPending arphost;
-                arphost = failedARPReqList.get(i);
+                arphost = entry.getValue();
                 if (hostFinder == null) {
                     logger.warn("ARPHandler Services are not available on subnet addition");
                     continue;
@@ -916,9 +909,20 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
         @Override
         public void run() {
             ARPPending arphost;
+
             /* This routine runs every 4 seconds */
-            for (int i = 0; i < ARPPendingList.size(); i++) {
-                arphost = ARPPendingList.get(i);
+            logger.trace("Number of Entries in ARP Pending/Failed Lists: ARPPendingList = {}, failedARPReqList = {}",
+                    ARPPendingList.size(), failedARPReqList.size());
+            for (Entry <InetAddress, ARPPending> entry : ARPPendingList.entrySet()) {
+                arphost = entry.getValue();
+
+                if (hostsDB.containsKey(arphost.getHostIP())) {
+                    // this host is already learned, shouldn't be in ARPPendingList
+                    // Remove it and continue
+                    logger.warn("Learned Host {} found in ARPPendingList", arphost.getHostIP());
+                    ARPPendingList.remove(entry.getKey());
+                    continue;
+                }
                 if (arphost.getSent_count() < switchManager.getHostRetryCount()) {
                     /*
                      * No reply has been received of first ARP Req, send the
@@ -937,7 +941,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
                      * ARP requests have been sent without receiving a
                      * reply, remove this from the pending list
                      */
-                    removePendingARPFromList(i);
+                    ARPPendingList.remove(entry.getKey());
                     logger.debug("ARP reply not received after multiple attempts, removing from Pending List IP: {}",
                             arphost.getHostIP().getHostAddress());
                     /*
@@ -945,10 +949,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
                      * on link up events
                      */
                     logger.debug("Adding the host to FailedARPReqList IP: {}", arphost.getHostIP().getHostAddress());
-                    failedARPReqList.add(arphost);
+                    failedARPReqList.put(entry.getKey(), arphost);
 
                 } else {
-                    logger.error("Inavlid arp_sent count for entry at index: {}", i);
+                    logger.error("Inavlid arp_sent count for entry: {}", entry);
                 }
             }
         }
@@ -1075,6 +1079,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
              */
             if (switchManager.isNodeConnectorEnabled(nc)) {
                 learnNewHost(host);
+                processPendingARPReqs(networkAddr);
                 notifyHostLearnedOrRemoved(host, true);
             } else {
                 inactiveStaticHosts.put(nc, host);
@@ -1286,11 +1291,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
 
     private void handleNodeConnectorStatusUp(NodeConnector nodeConnector) {
         ARPPending arphost;
+        HostNodeConnector host = null;
 
         logger.debug("handleNodeConnectorStatusUp {}", nodeConnector);
 
-        for (int i = 0; i < failedARPReqList.size(); i++) {
-            arphost = failedARPReqList.get(i);
+        for (Entry <InetAddress, ARPPending> entry : failedARPReqList.entrySet()) {
+            arphost = entry.getValue();
             logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress());
             if (hostFinder == null) {
                 logger.warn("ARPHandler is not available at interface  up");
@@ -1298,12 +1304,26 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
                         nodeConnector);
                 continue;
             }
-            hostFinder.find(arphost.getHostIP());
+
+            // Send a broadcast ARP only on the interface which just came up.
+            // Use hostFinder's "probe" method
+            try {
+                byte[] dataLayerAddress = NetUtils.getBroadcastMACAddr();
+                host = new HostNodeConnector(dataLayerAddress, arphost.getHostIP(), nodeConnector, (short) 0);
+                hostFinder.probe(host);
+            } catch (ConstructionException e) {
+                logger.debug("HostNodeConnector couldn't be created for Host: {}, NodeConnector: {}",
+                        arphost.getHostIP(), nodeConnector);
+                logger.error("", e);
+            }
+            logger.debug("Done. handleNodeConnectorStatusUp {}", nodeConnector);
         }
-        HostNodeConnector host = inactiveStaticHosts.get(nodeConnector);
+
+        host = inactiveStaticHosts.get(nodeConnector);
         if (host != null) {
             inactiveStaticHosts.remove(nodeConnector);
             learnNewHost(host);
+            processPendingARPReqs(host.getNetworkAddress());
             notifyHostLearnedOrRemoved(host, true);
         }
     }
@@ -1383,6 +1403,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
      *
      */
     void start() {
+        registerWithOSGIConsole();
     }
 
     /**
@@ -1429,4 +1450,30 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
             boolean originLocal) {
     }
 
+    private void registerWithOSGIConsole() {
+        BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+        bundleContext.registerService(CommandProvider.class.getName(), this, null);
+    }
+
+    @Override
+    public String getHelp() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void _dumpPendingARPReqList(CommandInterpreter ci) {
+        ARPPending arphost;
+        for (Entry <InetAddress, ARPPending> entry : ARPPendingList.entrySet()) {
+            arphost = entry.getValue();
+            ci.println(arphost.getHostIP().toString());
+        }
+    }
+
+    public void _dumpFailedARPReqList(CommandInterpreter ci) {
+        ARPPending arphost;
+        for (Entry <InetAddress, ARPPending> entry : failedARPReqList.entrySet()) {
+            arphost = entry.getValue();
+            ci.println(arphost.getHostIP().toString());
+        }
+    }
 }
index b5e66296c13591e44ec2c7193411322f07cba15e..3734a63e56c5106c58efdbe5145304fc657f1db6 100644 (file)
@@ -99,6 +99,8 @@ public class HostTrackerIT {
 
                 // needed by forwardingrulesmanager
                 mavenBundle("org.opendaylight.controller", "switchmanager").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "forwardingrulesmanager").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "statisticsmanager").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller", "switchmanager.implementation").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller", "configuration").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller", "configuration.implementation").versionAsInProject(),
index f98189319becc8ccae7557a7028378f38843b72e..9f47e0c9718f542f49d6bea3079045c482359230 100644 (file)
@@ -13,6 +13,8 @@ import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
 import org.opendaylight.controller.usermanager.IUserManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class NorthboundUtils {
 
@@ -37,6 +39,10 @@ public class NorthboundUtils {
         }
     };
 
+    private static final String AUDIT = "audit";
+
+    private static final Logger logger = LoggerFactory.getLogger(AUDIT);
+
     // Suppress default constructor for noninstantiability
     private NorthboundUtils() {
     }
@@ -114,4 +120,20 @@ public class NorthboundUtils {
         return true;
     }
 
+    public static void auditlog(String moduleName, String user, String action, String resource,
+            String containerName) {
+        String auditMsg = "";
+        String mode = "REST";
+        if (containerName != null) {
+            auditMsg = "Mode: " + mode + " User " + user + " "  + action + " " + moduleName + " " + resource + " in container "
+                    + containerName;
+        } else {
+            auditMsg = "Mode: " + mode + " User " + user + " "  + action + " " + moduleName + " " + resource;
+        }
+        logger.info(auditMsg);
+    }
+
+    public static void auditlog(String moduleName, String user, String action, String resource) {
+        auditlog(moduleName, user, action, resource, null);
+    }
 }
index d3cbc4aceed0ad88a887d3a870a7d184b35a85df..6bccc2d2e9ff25bde94925be51f4555f409c5e98 100644 (file)
@@ -322,7 +322,9 @@ public class FlowProgrammerNorthbound {
         }
 
         Status status = frm.addStaticFlow(flowConfig.getValue());
+
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Flow", username, "added", name, containerName);
             return Response.status(Response.Status.CREATED).build();
         }
         throw new InternalServerErrorException(status.getDescription());
@@ -385,6 +387,7 @@ public class FlowProgrammerNorthbound {
 
         Status status = frm.removeStaticFlow(name, node);
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Flow", username, "removed", name, containerName);
             return Response.ok().build();
         }
         throw new InternalServerErrorException(status.getDescription());
@@ -446,6 +449,7 @@ public class FlowProgrammerNorthbound {
 
         Status status = frm.toggleStaticFlowStatus(staticFlow);
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Flow", username, "toggled", name, containerName);
             return Response.ok().build();
         }
         throw new InternalServerErrorException(status.getDescription());
index 642c5ccbaa9db016aad4e68c99eff7087081cdd3..285967522caa4d99c85515f4a491eafec66f23b8 100644 (file)
@@ -310,6 +310,7 @@ public class HostTrackerNorthbound {
         Status status = hostTracker.addStaticHost(networkAddress,
                 dataLayerAddress, nc, vlan);
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Static Host", username, "added", networkAddress, containerName);
             return Response.status(Response.Status.CREATED).build();
         } else if (status.getCode().equals(StatusCode.BADREQUEST)) {
             throw new UnsupportedMediaTypeException(status.getDescription());
@@ -364,6 +365,7 @@ public class HostTrackerNorthbound {
 
         Status status = hostTracker.removeStaticHost(networkAddress);
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Static Host", username, "removed", networkAddress, containerName);
             return Response.ok().build();
         }
         throw new InternalServerErrorException(status.getDescription());
index b85f5641c73ea9af99fd3b201909220367c8240b..3deb8dfa7b59766fab862b6151e3b2f00e4fc6d3 100644 (file)
@@ -58,8 +58,7 @@ import org.opendaylight.controller.sal.utils.Status;
 @Path("/")
 public class StaticRoutingNorthbound {
 
-
-        private String username;
+    private String username;
 
     @Context
     public void setSecurityContext(SecurityContext context) {
@@ -197,6 +196,7 @@ public class StaticRoutingNorthbound {
                 sRoute.getPrefix(), sRoute.getNextHop());
         Status response = staticRouting.addStaticRoute(cfgObject);
         if (response.isSuccess()) {
+            NorthboundUtils.auditlog("Static Route", username, "added", name, containerName);
             return Response.status(Response.Status.CREATED).build();
         }
         throw new ResourceConflictException(response.getDescription());
@@ -241,6 +241,7 @@ public class StaticRoutingNorthbound {
 
         Status status = staticRouting.removeStaticRoute(name);
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Static Route", username, "removed", name, containerName);
             return Response.ok().build();
         }
         throw new ResourceNotFoundException(status.getDescription());
index 17780fc70db079034f7111c47cf420368f82edd7..8c555f26738536c95eed13580d609fd240e9032c 100644 (file)
@@ -160,6 +160,7 @@ public class SubnetsNorthboundJAXRS {
         SubnetConfig cfgObject = new SubnetConfig(subnetName, subnet, new HashSet<String>(0));
         Status status = switchManager.addSubnet(cfgObject);
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Subnet Gateway", username, "added", subnetName, containerName);
             return Response.status(Response.Status.CREATED).build();
         }
         throw new InternalServerErrorException(status.getDescription());
@@ -198,6 +199,7 @@ public class SubnetsNorthboundJAXRS {
         }
         Status status = switchManager.removeSubnet(subnetName);
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Subnet Gateway", username, "removed", subnetName, containerName);
             return Response.status(Response.Status.OK).build();
         }
         throw new InternalServerErrorException(status.getDescription());
@@ -274,6 +276,9 @@ public class SubnetsNorthboundJAXRS {
             for (String s : newPorts) {
                 Status st = switchManager.addPortsToSubnet(name, s);
                 successful = successful && st.isSuccess();
+                if(successful){
+                    NorthboundUtils.auditlog("Subnet Gateway", username, "added", s +" to "+name, containerName);
+                }
             }
         }
 
@@ -393,6 +398,9 @@ public class SubnetsNorthboundJAXRS {
                 for (String port : ports) {
                     st = switchManager.addPortsToSubnet(name, port);
                     successful = successful && st.isSuccess();
+                    if(successful){
+                        NorthboundUtils.auditlog("Subnet Gateway", username, "added",  st +" to "+name, containerName);
+                    }
                 }
             } else if (action.equals("delete")) {
                 // delete existing ports
@@ -400,6 +408,9 @@ public class SubnetsNorthboundJAXRS {
                 for (String port : ports) {
                     st = switchManager.removePortsFromSubnet(name, port);
                     successful = successful && st.isSuccess();
+                    if(successful){
+                        NorthboundUtils.auditlog("Subnet Gateway", username, "removed",  st +" from "+name, containerName);
+                    }
                 }
             } else {
                 return Response.status(Response.Status.BAD_REQUEST).build();
index d6d9be9e9fbc7cc5baa43f9376019e6d9f7ce1e2..e67d1b75686934b48fb15cb409bf0cdf5cd3d123 100644 (file)
@@ -303,6 +303,9 @@ public class SwitchNorthbound {
                 nodeProperties.remove(propertyName.toLowerCase());
                 SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
                 status = switchManager.updateNodeConfig(newSwitchConfig);
+                if(status.isSuccess()){
+                    NorthboundUtils.auditlog("Static Route", username, "updated", nodeId, containerName);
+                }
             }
         }
         return NorthboundUtils.getResponse(status);
@@ -519,6 +522,7 @@ public class SwitchNorthbound {
                 .fromStringNoNode(nodeConnectorType, nodeConnectorId, node);
         Status ret = switchManager.removeNodeConnectorProp(nc, propertyName);
         if (ret.isSuccess()) {
+            NorthboundUtils.auditlog("Node Connector Property", username, "removed", nc + " from " + nodeConnectorId, containerName);
             return Response.ok().build();
         }
         throw new ResourceNotFoundException(ret.getDescription());
index 323e2d2211deaa916ce5b81257bde2074592aa65..fb4e8229ff48fd87dd8e6195ee272d497bfbd095 100644 (file)
@@ -195,6 +195,7 @@ public class TopologyNorthboundJAXRS {
 
         Status status = topologyManager.addUserLink(userLinkConfig.getValue());
         if (status.isSuccess()) {
+            NorthboundUtils.auditlog("User Link", username, "added", userLinkConfig.getValue().getName(), containerName);
             return Response.status(Response.Status.CREATED).build();
         }
         throw new InternalServerErrorException(status.getDescription());
@@ -236,6 +237,7 @@ public class TopologyNorthboundJAXRS {
 
         Status ret = topologyManager.deleteUserLink(name);
         if (ret.isSuccess()) {
+            NorthboundUtils.auditlog("User Link", username, "removed", name, containerName);
             return Response.ok().build();
         }
         throw new ResourceNotFoundException(ret.getDescription());
index a5a071122f62d6b0d0df9b45fb1f8b2775aa347e..f983e1244dba519f7a2afc0c6d13f8937f1178bc 100644 (file)
@@ -22,7 +22,6 @@ import org.opendaylight.controller.protocol_plugin.openflow.IInventoryProvider;
 import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimInternalListener;
 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
-import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.core.Property;
@@ -45,11 +44,11 @@ public class InventoryService implements IInventoryShimInternalListener,
         IPluginInInventoryService, IInventoryProvider {
     protected static final Logger logger = LoggerFactory
             .getLogger(InventoryService.class);
-    private Set<IPluginOutInventoryService> pluginOutInventoryServices =
+    private final Set<IPluginOutInventoryService> pluginOutInventoryServices =
             new CopyOnWriteArraySet<IPluginOutInventoryService>();
     private IController controller = null;
-    private ConcurrentMap<Node, Map<String, Property>> nodeProps; // properties are maintained in global container only
-    private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps; // properties are maintained in global container only
+    private ConcurrentMap<Node, Map<String, Property>> nodeProps;
+    private ConcurrentMap<NodeConnector, Map<String, Property>> nodeConnectorProps;
     private boolean isDefaultContainer = false;
     private String containerName = null;
 
index 5075e58281132a4404ab8473be01e05ea5305115..b2a1cfe8c2824b8bfab8a4b737d949e9d67df446 100644 (file)
@@ -147,10 +147,11 @@ public class ICMP extends Packet {
     short computeChecksum(byte[] data, int start) {
         int sum = 0, carry = 0, finalSum = 0;
         int wordData;
-        int end = start + this.getHeaderSize() / NetUtils.NumBitsInAByte
-                + rawPayload.length;
-        int checksumStartByte = start + getfieldOffset(CHECKSUM)
-                / NetUtils.NumBitsInAByte;
+        int end = start + this.getHeaderSize() / NetUtils.NumBitsInAByte;
+        if (rawPayload != null) {
+            end += rawPayload.length;
+        }
+        int checksumStartByte = start + getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte;
 
         for (int i = start; i <= (end - 1); i = i + 2) {
             // Skip, if the current bytes are checkSum bytes
index f81e7e3d03b0c4af14f5e539b45567725d80c43b..0fce4f4b0aea447a26c2884a1d6b6b3814ba9df5 100644 (file)
@@ -12,6 +12,7 @@ import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -502,4 +503,14 @@ public abstract class NetUtils {
             return null;
         }
     }
+
+    /**
+     * Returns Broadcast MAC Address
+     *
+     * @return the byte array containing  broadcaset mac address
+     */
+    public static byte[] getBroadcastMACAddr() {
+        return Arrays.copyOf(BroadcastMACAddr, BroadcastMACAddr.length);
+    }
+
 }
index bcb9e0b19254402ba732b7f6fb74b0a20525b24a..f86f521bd2b032cebdd5bba5c568127d2cfb6166 100644 (file)
@@ -48,7 +48,9 @@
               org.opendaylight.controller.sal.core,
               org.opendaylight.controller.sal.utils,
               org.opendaylight.controller.sal.packet,
+              org.opendaylight.controller.sal.reader,
               org.opendaylight.controller.sal.inventory,
+              org.opendaylight.controller.statisticsmanager,
               org.slf4j,
               org.apache.felix.dm,
               org.eclipse.osgi.framework.console,
       <artifactId>switchmanager</artifactId>
       <version>0.5.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>statisticsmanager</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 </project>
index b574269e450e46b2ee39b532208aadc00c024a4d..0cb55d6555903498b52a29aa492680d58bcf4780 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.controller.configuration.IConfigurationContainerAware;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
 import org.opendaylight.controller.sal.inventory.IInventoryService;
 import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
+import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
 import org.opendaylight.controller.switchmanager.IInventoryListener;
 import org.opendaylight.controller.switchmanager.ISpanAware;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
@@ -106,6 +107,10 @@ public class Activator extends ComponentActivatorAbstractBase {
                     IInventoryService.class).setCallbacks(
                     "setInventoryService", "unsetInventoryService")
                     .setRequired(false));
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IStatisticsManager.class).setCallbacks(
+                    "setStatisticsManager", "unsetStatisticsManager")
+                    .setRequired(false));
             c.add(createContainerServiceDependency(containerName).setService(
                     ISwitchManagerAware.class).setCallbacks(
                     "setSwitchManagerAware", "unsetSwitchManagerAware")
index 4c4adf047853410d325b5d67fad2c197ef66866e..6bd89a806e3174b13c074038a2fecef86859bf97 100644 (file)
@@ -54,6 +54,7 @@ import org.opendaylight.controller.sal.core.Tier;
 import org.opendaylight.controller.sal.core.UpdateType;
 import org.opendaylight.controller.sal.inventory.IInventoryService;
 import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
+import org.opendaylight.controller.sal.reader.NodeDescription;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.IObjectReader;
@@ -61,6 +62,7 @@ import org.opendaylight.controller.sal.utils.ObjectReader;
 import org.opendaylight.controller.sal.utils.ObjectWriter;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
 import org.opendaylight.controller.switchmanager.IInventoryListener;
 import org.opendaylight.controller.switchmanager.ISpanAware;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
@@ -104,6 +106,7 @@ CommandProvider {
     private ConcurrentMap<Node, Map<String, NodeConnector>> nodeConnectorNames;
     private ConcurrentMap<String, Property> controllerProps;
     private IInventoryService inventoryService;
+    private IStatisticsManager statisticsManager;
     private final Set<ISwitchManagerAware> switchManagerAware = Collections
             .synchronizedSet(new HashSet<ISwitchManagerAware>());
     private final Set<IInventoryListener> inventoryListeners = Collections
@@ -698,18 +701,42 @@ CommandProvider {
         }
 
         Map<String, Property> updateProperties = switchConfig.getNodeProperties();
-        String nodeId = switchConfig.getNodeId();
         ForwardingMode mode = (ForwardingMode) updateProperties.get(ForwardingMode.name);
         if (mode != null) {
             if (isDefaultContainer) {
                 if (!mode.isValid()) {
-                    return new Status(StatusCode.BADREQUEST, "Invalid Forwarding Mode Value.");
+                    return new Status(StatusCode.BADREQUEST, "Invalid Forwarding Mode Value");
                 }
             } else {
                 return new Status(StatusCode.NOTACCEPTABLE,
                         "Forwarding Mode modification is allowed only in default container");
             }
         }
+
+        Description description = (Description) switchConfig.getProperty(Description.propertyName);
+        String nodeId = switchConfig.getNodeId();
+        Node node = Node.fromString(nodeId);
+        NodeDescription nodeDesc = (this.statisticsManager == null) ? null : this.statisticsManager
+                .getNodeDescription(node);
+        String advertisedDesc = (nodeDesc == null) ? "" : nodeDesc.getDescription();
+        if (description != null && description.getValue() != null) {
+            if (description.getValue().isEmpty() || description.getValue().equals(advertisedDesc)) {
+                updateProperties.remove(Description.propertyName);
+                switchConfig = new SwitchConfig(nodeId, updateProperties);
+            } else {
+                // check if description is configured or was published by any other node
+                for (Node n : nodeProps.keySet()) {
+                    Description desc = (Description) getNodeProp(n, Description.propertyName);
+                    NodeDescription nDesc = (this.statisticsManager == null) ? null : this.statisticsManager
+                            .getNodeDescription(n);
+                    String advDesc = (nDesc == null) ? "" : nDesc.getDescription();
+                    if ((description.equals(desc) || description.getValue().equals(advDesc)) && !node.equals(n)) {
+                        return new Status(StatusCode.CONFLICT, "Node name already in use");
+                    }
+                }
+            }
+        }
+
         boolean modeChange = false;
         SwitchConfig sc = nodeConfigList.get(nodeId);
         Map<String, Property> prevNodeProperties = new HashMap<String, Property>();
@@ -743,30 +770,27 @@ CommandProvider {
                 }
             }
         }
-        Node node = Node.fromString(nodeId);
         Map<String, Property> propMapCurr = nodeProps.get(node);
         if (propMapCurr == null) {
             return new Status(StatusCode.SUCCESS);
         }
         Map<String, Property> propMap = new HashMap<String, Property>(propMapCurr);
-        if (!prevNodeProperties.isEmpty()) {
-            for (String prop : prevNodeProperties.keySet()) {
-                if (!updateProperties.containsKey(prop)) {
-                    if (prop.equals(Description.propertyName)) {
-                        Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
-                        if (nodeProp.get(node) != null) {
-                            propMap.put(Description.propertyName, nodeProp.get(node).get(Description.propertyName));
-                            continue;
-                        }
+        for (String prop : prevNodeProperties.keySet()) {
+            if (!updateProperties.containsKey(prop)) {
+                if (prop.equals(Description.propertyName)) {
+                    if (!advertisedDesc.isEmpty()) {
+                        Property desc = new Description(advertisedDesc);
+                        propMap.put(Description.propertyName, desc);
                     }
-                    propMap.remove(prop);
+                    continue;
                 }
+                propMap.remove(prop);
             }
         }
         propMap.putAll(updateProperties);
         if (!nodeProps.replace(node, propMapCurr, propMap)) {
             // TODO rollback using Transactionality
-            return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration.");
+            return new Status(StatusCode.CONFLICT, "Cluster conflict: Unable to update node configuration");
         }
         if (modeChange) {
             notifyModeChange(node, (mode == null) ? false : mode.isProactive());
@@ -887,7 +911,7 @@ CommandProvider {
     }
 
     @Override
-    public void entryUpdated(Long key, String new_value, String cacheName,
+    public void entryUpdated(Long key, String newValue, String cacheName,
             boolean originLocal) {
         saveSwitchConfigInternal();
     }
@@ -1446,9 +1470,13 @@ CommandProvider {
                         }
                     }
                     map.remove(name.getValue());
-                    if (!nodeConnectorNames.replace(node, mapCurr, map)) {
-                        log.warn("Cluster conflict: Unable remove Name property of nodeconnector {}, skip.",
-                                nodeConnector.getID());
+                    if (map.isEmpty()) {
+                        nodeConnectorNames.remove(node);
+                    } else {
+                        if (!nodeConnectorNames.replace(node, mapCurr, map)) {
+                            log.warn("Cluster conflict: Unable remove Name property of nodeconnector {}, skip.",
+                                    nodeConnector.getID());
+                        }
                     }
                 }
 
@@ -1532,6 +1560,16 @@ CommandProvider {
         clearInventories();
     }
 
+    public void setStatisticsManager(IStatisticsManager statisticsManager) {
+        log.trace("Got statistics manager set request {}", statisticsManager);
+        this.statisticsManager = statisticsManager;
+    }
+
+    public void unsetStatisticsManager(IStatisticsManager statisticsManager) {
+        log.trace("Got statistics manager UNset request");
+        this.statisticsManager = null;
+    }
+
     public void setSwitchManagerAware(ISwitchManagerAware service) {
         log.trace("Got inventory service set request {}", service);
         if (this.switchManagerAware != null) {
@@ -2024,12 +2062,6 @@ CommandProvider {
         nodeProps.put(node, propMap);
     }
 
-    private void removeNodeProps(Node node) {
-        if (getUpNodeConnectors(node).size() == 0) {
-            nodeProps.remove(node);
-        }
-    }
-
     @Override
     public Status saveConfiguration() {
         return saveSwitchConfig();
index 39a9cceb085fc68cade5c53d961b06a8a9c8d6b2..54dbbdcce0b0b2d59b1494bb241829a9c17633e4 100644 (file)
@@ -110,6 +110,10 @@ public class SwitchManagerIT {
                                 "protocol_plugins.stub").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller", "switchmanager")
                         .versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "topologymanager").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "hosttracker").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "forwardingrulesmanager").versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "statisticsmanager").versionAsInProject(),
                 mavenBundle("org.opendaylight.controller",
                         "switchmanager.implementation").versionAsInProject(),
                 mavenBundle("org.jboss.spec.javax.transaction",
index f92e92ec17ea6a2a9ffc515f495855aaa2aac36e..15ad9e9887d8eb2aba1250bc278a48f7441db00a 100644 (file)
@@ -256,6 +256,7 @@ public class Devices implements IDaylightWeb {
             } else {
                 resultBean.setStatus(true);
                 resultBean.setMessage("Updated node information successfully");
+                DaylightWebUtil.auditlog("Node", userName, "updated", nodeId + " to "+ nodeName, containerName);
             }
         } catch (Exception e) {
             resultBean.setStatus(false);
@@ -338,6 +339,7 @@ public class Devices implements IDaylightWeb {
             if (addStaticRouteResult.isSuccess()) {
                 result.setStatus(true);
                 result.setMessage("Static Route saved successfully");
+                DaylightWebUtil.auditlog("Static Route", userName, "added", routeName, containerName);
             } else {
                 result.setStatus(false);
                 result.setMessage(addStaticRouteResult.getDescription());
@@ -381,6 +383,7 @@ public class Devices implements IDaylightWeb {
                     resultBean.setMessage(result.getDescription());
                     break;
                 }
+                DaylightWebUtil.auditlog("Static Route", userName, "removed", route, containerName);
             }
         } catch (Exception e) {
             resultBean.setStatus(false);
@@ -451,6 +454,7 @@ public class Devices implements IDaylightWeb {
             if (result.isSuccess()) {
                 resultBean.setStatus(true);
                 resultBean.setMessage("Added gateway address successfully");
+                DaylightWebUtil.auditlog("Subnet Gateway", userName, "added", gatewayName, containerName);
             } else {
                 resultBean.setStatus(false);
                 resultBean.setMessage(result.getDescription());
@@ -491,6 +495,7 @@ public class Devices implements IDaylightWeb {
                     resultBean.setMessage(result.getDescription());
                     break;
                 }
+                DaylightWebUtil.auditlog("Subnet Gateway", userName, "removed", subnet, containerName);
             }
         } catch (Exception e) {
             resultBean.setStatus(false);
@@ -526,6 +531,7 @@ public class Devices implements IDaylightWeb {
                 resultBean.setStatus(true);
                 resultBean
                         .setMessage("Added ports to subnet gateway address successfully");
+                DaylightWebUtil.auditlog("Ports to Subnet Gateway", userName, "added",nodeId+"/"+ ports, containerName);
             } else {
                 resultBean.setStatus(false);
                 resultBean.setMessage(result.getDescription());
@@ -564,6 +570,7 @@ public class Devices implements IDaylightWeb {
                 resultBean.setStatus(true);
                 resultBean
                         .setMessage("Deleted port from subnet gateway address successfully");
+                DaylightWebUtil.auditlog("Ports from Subnet Gateway", userName, "removed", nodePort, containerName);
             } else {
                 resultBean.setStatus(false);
                 resultBean.setMessage(result.getDescription());
@@ -695,6 +702,7 @@ public class Devices implements IDaylightWeb {
             if (result.isSuccess()) {
                 resultBean.setStatus(true);
                 resultBean.setMessage("SPAN Port added successfully");
+                DaylightWebUtil.auditlog("SPAN Port", userName, "added", cfgObject.getNodeId(), containerName);
             } else {
                 resultBean.setStatus(false);
                 resultBean.setMessage(result.getDescription());
@@ -740,6 +748,7 @@ public class Devices implements IDaylightWeb {
                         resultBean.setMessage(result.getDescription());
                         break;
                     }
+                    DaylightWebUtil.auditlog("SPAN Port", userName, "removed", cfgObject.getNodeId(), containerName);
                 }
             }
         } catch (Exception e) {
index 38df0455264c51d929c6ed3405a7f714ab4fe63a..f48a46d204ac05a2c50ae5859bf6a59dc3b8d57b 100644 (file)
@@ -12,10 +12,10 @@ one.f = {};
 // specify dashlets and layouts
 
 one.f.dashlet = {
-       nodesLearnt : {
-               id : 'nodesLearnt',
-           name : 'Nodes Learnt'
-       },
+    nodesLearnt : {
+        id : 'nodesLearnt',
+        name : 'Nodes Learnt'
+    },
     staticRouteConfig : {
         id : 'staticRouteConfig',
         name : 'Static Route Configuration'
@@ -50,67 +50,77 @@ one.f.menu = {
 
 /**Devices Modules */
 one.f.switchmanager = {
-       rootUrl: "controller/web/devices",
-       createTable: function(columnNames, body) {
-               var tableAttributes = ["table-striped", "table-bordered", "table-condensed"];
-               var $table = one.lib.dashlet.table.table(tableAttributes);
-               var tableHeaders = columnNames;
-               var $thead = one.lib.dashlet.table.header(tableHeaders);
-               var $tbody = one.lib.dashlet.table.body(body, tableHeaders);
-               $table.append($thead)
-               .append($tbody);
-               return $table;
-       },
-       validateName: function(name) {
+    rootUrl: "controller/web/devices",
+    createTable: function(columnNames, body) {
+        var tableAttributes = ["table-striped", "table-bordered", "table-condensed"];
+        var $table = one.lib.dashlet.table.table(tableAttributes);
+        var tableHeaders = columnNames;
+        var $thead = one.lib.dashlet.table.header(tableHeaders);
+        var $tbody = one.lib.dashlet.table.body(body, tableHeaders);
+        $table.append($thead)
+        .append($tbody);
+        return $table;
+    },
+    validateName: function(name) {
         return (name.length < 256);
-       }
+    }
 };
 
 one.f.switchmanager.nodesLearnt = {
-       id: {
-               dashlet: {
-                       popout: "one_f_switchmanager_nodesLearnt_id_dashlet_popout"
-               },
-               modal: {
-                       modal: "one_f_switchmanager_nodesLearnt_id_modal_modal",
-                       save: "one_f_switchmanager_nodesLearnt_id_modal_save",
-                       form: {
-                               nodeId: "one_f_switchmanager_nodesLearnt_id_modal_form_nodeid",
-                               nodeName : "one_f_switchmanager_nodesLearnt_id_modal_form_nodename",
-                               portStatus : "one_f_switchmanager_nodesLearnt_id_modal_form_portstatus",
-                               tier: "one_f_switchmanager_nodesLearnt_id_modal_form_tier",
-                               operationMode: "one_f_switchmanager_nodesLearnt_id_modal_form_opmode"
-                       }
-               }
-       },
-       dashlet: function($dashlet) {
-               var url = one.f.switchmanager.rootUrl + "/nodesLearnt";
-               one.lib.dashlet.empty($dashlet);
-               $dashlet.append(one.lib.dashlet.header(one.f.dashlet.nodesLearnt.name));
-
-               one.f.switchmanager.nodesLearnt.ajax.main(url, function(content) {
-                       var body = one.f.switchmanager.nodesLearnt.data.abridged(content);
-                       var $table = one.f.switchmanager.createTable(["Node Name", "Node ID", "Ports"], body);
-                       $dashlet.append($table);
-               });
-       },
-       ajax : {
-               main : function(url, callback) {
-                       $.getJSON(url, function(data) {
-                               callback(data);
-                       });
-               }
-       },
-       modal : {
-               initialize: {
-                       updateNode: function(evt) {
-                   one.f.switchmanager.nodesLearnt.ajax.main(one.f.switchmanager.rootUrl + "/tiers", function(tiers) {
+    id: {
+        dashlet: {
+            popout: "one_f_switchmanager_nodesLearnt_id_dashlet_popout",
+            datagrid: "one_f_switchmanager_nodesLearnt_id_dashlet_datagrid"
+        },
+        modal: {
+            modal: "one_f_switchmanager_nodesLearnt_id_modal_modal",
+            save: "one_f_switchmanager_nodesLearnt_id_modal_save",
+            datagrid: "one_f_switchmanager_nodesLearnt_id_modal_datagrid",
+            form: {
+                nodeId: "one_f_switchmanager_nodesLearnt_id_modal_form_nodeid",
+                nodeName : "one_f_switchmanager_nodesLearnt_id_modal_form_nodename",
+                portStatus : "one_f_switchmanager_nodesLearnt_id_modal_form_portstatus",
+                tier: "one_f_switchmanager_nodesLearnt_id_modal_form_tier",
+                operationMode: "one_f_switchmanager_nodesLearnt_id_modal_form_opmode"
+            }
+        }
+    },
+    dashlet: function($dashlet) {
+        var url = one.f.switchmanager.rootUrl + "/nodesLearnt";
+        one.lib.dashlet.empty($dashlet);
+        $dashlet.append(one.lib.dashlet.header(one.f.dashlet.nodesLearnt.name));
+
+        one.f.switchmanager.nodesLearnt.ajax.main(url, function(content) {
+            var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.nodesLearnt.id.dashlet.datagrid, {
+                searchable: true,
+                filterable: false,
+                pagination: true,
+                flexibleRowsPerPage: true
+                }, "table-striped table-condensed");
+            $dashlet.append($gridHTML);
+            var dataSource = one.f.switchmanager.nodesLearnt.data.gridDataSource.abridged(content);
+            $("#" + one.f.switchmanager.nodesLearnt.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() {
+                $(this).find("tbody a").click(one.f.switchmanager.nodesLearnt.modal.initialize.updateNode);
+            });
+        });
+    },
+    ajax : {
+        main : function(url, callback) {
+            $.getJSON(url, function(data) {
+                callback(data);
+            });
+        }
+    },
+    modal : {
+        initialize: {
+            updateNode: function(evt) {
+                one.f.switchmanager.nodesLearnt.ajax.main(one.f.switchmanager.rootUrl + "/tiers", function(tiers) {
 
                     var nodeId = decodeURIComponent(evt.target.id);
                     var h3;
                     var footer = [];
-                    var $body = one.f.switchmanager.nodesLearnt.modal.body.updateNode(nodeId, evt.target.switchDetails, tiers);
-                    if (evt.target.privilege == 'WRITE'){
+                    var $body = one.f.switchmanager.nodesLearnt.modal.body.updateNode(nodeId, JSON.parse(decodeURIComponent(evt.target.getAttribute("switchDetails"))), tiers);
+                    if (evt.target.getAttribute("privilege") == 'WRITE'){
                         h3 = "Update Node Information";
                         footer = one.f.switchmanager.nodesLearnt.modal.footer.updateNode();
                     } else { //disable node edit
@@ -124,121 +134,201 @@ one.f.switchmanager.nodesLearnt = {
                         one.f.switchmanager.nodesLearnt.modal.save($modal);
                     });
 
-                       // inject body (nodePorts)
-                       one.lib.modal.inject.body($modal, $body);
-                       $modal.modal();
-                   });
-                       },
-                       popout: function() {
-                               var h3 = "Nodes Learnt";
-                   var footer = one.f.switchmanager.nodesLearnt.modal.footer.popout();
-                   var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.modal, h3, "", footer);
-                   var $body = one.f.switchmanager.nodesLearnt.modal.body.popout($modal);
-                   return $modal;
-                       }
-               },
-               body: {
-                       updateNode: function(nodeId, switchDetails, tiers) {
-                               var $form = $(document.createElement('form'));
-                               var $fieldset = $(document.createElement('fieldset'));
-                               // node ID. not editable.
-                               var $label = one.lib.form.label("Node ID");
-                               var $input = one.lib.form.input("node id");
-                               $input.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.nodeId);
-                               $input.attr("disabled", true);
-                               $input.attr("value", nodeId);
-                               $fieldset.append($label).append($input);
-                               // node name
-                               var $label = one.lib.form.label("Node Name");
-                               var $input = one.lib.form.input("Node Name");
-                               $input.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.nodeName);
-                               if(switchDetails["nodeName"] != null) {
-                                       $input.attr('value', switchDetails["nodeName"]);
-                               }
-                               $fieldset.append($label).append($input);
-                               // node tier
-                               var $label = one.lib.form.label("Tier");
-                               var $select = one.lib.form.select.create(tiers);
-                               $select.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.tier);
-                               $select.val(switchDetails["tier"]);
-                               $fieldset.append($label).append($select);
-                               // operation mode
-                               var $label = one.lib.form.label("Operation Mode");
-                               var $select = one.lib.form.select.create(
-                                               ["Allow reactive forwarding", "Proactive forwarding only"]);
-                               $select.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.operationMode);
-                               if ((one.main.registry != undefined) && (one.main.registry.container != 'default')) {
-                                       $select.attr("disabled", true);
-                               }
-                               $select.val(switchDetails["mode"]);
-                               $fieldset.append($label).append($select);
-                               $form.append($fieldset);
-                               return $form;
-                       },
-                       popout: function($modal) {
-                               var url = one.f.switchmanager.rootUrl + "/nodesLearnt";
-                               one.f.switchmanager.nodesLearnt.ajax.main(url, function(content) {
-                                       var tableContent = one.f.switchmanager.nodesLearnt.data.popout(content);
-                                       var $table = one.f.switchmanager.createTable(content.columnNames, tableContent);
-                                       one.lib.modal.inject.body($modal, $table);
-                               });
-                       }
-               },
-               save: function($modal) {
-                       var result = {};
+                    // inject body (nodePorts)
+                    one.lib.modal.inject.body($modal, $body);
+                    $modal.modal();
+                });
+            },
+            popout: function() {
+                var h3 = "Nodes Learnt";
+                var footer = one.f.switchmanager.nodesLearnt.modal.footer.popout();
+                var $modal = one.lib.modal.spawn(one.f.switchmanager.nodesLearnt.id.modal.modal, h3, "", footer);
+                var $body = one.f.switchmanager.nodesLearnt.modal.body.popout($modal);
+                return $modal;
+            }
+        },
+        body: {
+            updateNode: function(nodeId, switchDetails, tiers) {
+                var $form = $(document.createElement('form'));
+                var $fieldset = $(document.createElement('fieldset'));
+                // node ID. not editable.
+                var $label = one.lib.form.label("Node ID");
+                var $input = one.lib.form.input("node id");
+                $input.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.nodeId);
+                $input.attr("disabled", true);
+                $input.attr("value", nodeId);
+                $fieldset.append($label).append($input);
+                // node name
+                var $label = one.lib.form.label("Node Name");
+                var $input = one.lib.form.input("Node Name");
+                $input.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.nodeName);
+                if(switchDetails["nodeName"] != null) {
+                    $input.attr('value', switchDetails["nodeName"]);
+                }
+                $fieldset.append($label).append($input);
+                // node tier
+                var $label = one.lib.form.label("Tier");
+                var $select = one.lib.form.select.create(tiers);
+                $select.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.tier);
+                $select.val(switchDetails["tier"]);
+                $fieldset.append($label).append($select);
+                // operation mode
+                var $label = one.lib.form.label("Operation Mode");
+                var $select = one.lib.form.select.create(
+                        ["Allow reactive forwarding", "Proactive forwarding only"]);
+                $select.attr('id', one.f.switchmanager.nodesLearnt.id.modal.form.operationMode);
+                if ((one.main.registry != undefined) && (one.main.registry.container != 'default')) {
+                    $select.attr("disabled", true);
+                }
+                $select.val(switchDetails["mode"]);
+                $fieldset.append($label).append($select);
+                $form.append($fieldset);
+                return $form;
+            },
+            popout: function($modal) {
+                var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.nodesLearnt.id.modal.datagrid, {
+                        searchable: true,
+                        filterable: false,
+                        pagination: true,
+                        flexibleRowsPerPage: true
+                        }, "table-striped table-condensed");
+                one.lib.modal.inject.body($modal, $gridHTML);
+                // attach to shown event of modal 
+                $modal.on("shown", function() {
+                    var url = one.f.switchmanager.rootUrl + "/nodesLearnt";
+                    one.f.switchmanager.nodesLearnt.ajax.main(url, function(content) {
+                        var dataSource = one.f.switchmanager.nodesLearnt.data.gridDataSource.popout(content);
+                        $("#" + one.f.switchmanager.nodesLearnt.id.modal.datagrid).datagrid({
+                            dataSource: dataSource,
+                            stretchHeight: true
+                        });
+                    });
+                });
+            }
+        },
+        save: function($modal) {
+            var result = {};
             result['nodeName'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.nodeName, $modal).val();
             if(!one.f.switchmanager.validateName(result['nodeName'])) {
-               alert("Node name can contain upto 255 characters");
-               return;
+                alert("Node name can contain upto 255 characters");
+                return;
             }
             result['nodeId'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.nodeId, $modal).val();
             result['tier'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.tier, $modal).val();
             result['operationMode'] = $('#' + one.f.switchmanager.nodesLearnt.id.modal.form.operationMode, $modal).val();
             one.f.switchmanager.nodesLearnt.modal.ajax(result, 
-                               function(response) {
-                       if(response.status == true) {
-                               $modal.modal('hide');
-                               one.topology.update(); // refresh visual topology with new name
-                               // TODO: Identify dashlet by inserting a nodesLearnt div 
-                                       // in the dashlet() instead
-                               one.f.switchmanager.nodesLearnt.dashlet($("#left-top .dashlet"));
-                       } else {
-                               alert(response.message);
-                       }
-                       
-                   });
-               },
-               ajax: function(requestData, callback) {
-                       $.getJSON(one.f.switchmanager.rootUrl + "/nodesLearnt/update", requestData, function(response) {
-                               callback(response);
-                       });
-               },
-               footer: {
-                       updateNode: function() {
-                               var footer = [];
+                function(response) {
+                    if(response.status == true) {
+                        $modal.modal('hide');
+                        one.topology.update(); // refresh visual topology with new name
+                        // TODO: Identify dashlet by inserting a nodesLearnt div 
+                        // in the dashlet() instead
+                        one.f.switchmanager.nodesLearnt.dashlet($("#left-top .dashlet"));
+                    } else {
+                        alert(response.message);
+                    }
+                    
+                });
+        },
+        ajax: function(requestData, callback) {
+            $.getJSON(one.f.switchmanager.rootUrl + "/nodesLearnt/update", requestData, function(response) {
+                callback(response);
+            });
+        },
+        footer: {
+            updateNode: function() {
+                var footer = [];
                 var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.nodesLearnt.id.modal.save, "btn-success", "");
                 var $saveButton = one.lib.dashlet.button.button(saveButton);
                 footer.push($saveButton);
 
-                   return footer;
-                       },
-                       popout: function() {
-                               // TODO: Maybe put a close button in the footer?
-                               return [];
-                       }
-               }
-       },
-       // data functions
-       data : {
-               abridged : function(data) {
-                       var result = [];
-                       $.each(data.nodeData, function(key, value) {
-                               var tr = {};
-                               var entry = [];
-                               var nodenameentry = value["nodeName"] ? value["nodeName"] : "Click to update";
-
-                               // TODO: Move anchor tag creation to one.lib.form.
-                               var aTag;
+                return footer;
+            },
+            popout: function() {
+                // TODO: Maybe put a close button in the footer?
+                return [];
+            }
+        }
+    },
+    // data functions
+    data : {
+        gridDataSource: {
+            abridged: function(data) {
+                var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'nodeName',
+                            label: 'Node Name',
+                            sortable: true
+                        },
+                        {
+                            property: 'nodeId',
+                            label: 'Node ID',
+                            sortable: true
+                        },
+                        {
+                            property: 'ports',
+                            label: 'Ports',
+                            sortable: true
+                        }
+                    ],
+                    data: data.nodeData,
+                    formatter: function(items) {
+                    $.each(items, function (index, item) {
+                        var nodeNameEntry = item.nodeName ? item.nodeName : "Click to update";
+                        item.nodeName = '<a href="#" id="' + item.nodeId + '" switchDetails=' + encodeURIComponent(JSON.stringify(item)) + 
+                        ' privilege=' + data.privilege + '>' + nodeNameEntry + '</a>';
+                    }); 
+                    },
+                    delay: 0
+                });
+                return source;
+
+            },
+            popout: function(data) {
+                var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'nodeName',
+                            label: 'Node Name',
+                            sortable: true
+                        },
+                        {
+                            property: 'nodeId',
+                            label: 'Node ID',
+                            sortable: true
+                        },
+                        {
+                            property: 'tierName',
+                            label: 'Tier Name',
+                            sortable: true
+                        },
+                        {
+                            property: 'mac',
+                            label: 'Mac',
+                            sortable: true
+                        },
+                        {
+                            property: 'ports',
+                            label: 'Ports',
+                            sortable: true
+                        }
+                    ],
+                    data: data.nodeData,
+                    delay: 0
+                });
+                return source;
+            }
+        },
+        abridged : function(data) {
+            var result = [];
+            $.each(data.nodeData, function(key, value) {
+                var tr = {};
+                var entry = [];
+                var nodeNameEntry = value["nodeName"] ? value["nodeName"] : "Click to update";
+
+                // TODO: Move anchor tag creation to one.lib.form.
+                var aTag;
                 aTag = document.createElement("a");
                 aTag.privilege = data.privilege;
                 aTag.addEventListener("click", one.f.switchmanager.nodesLearnt.modal.initialize.updateNode);
@@ -247,61 +337,61 @@ one.f.switchmanager.nodesLearnt = {
                 }, false);
                 aTag.setAttribute("id", encodeURIComponent(value["nodeId"]));
                 aTag.switchDetails = value;
-                               aTag.innerHTML = nodenameentry;
-                               entry.push(aTag);
-                               entry.push(value["nodeId"]);
-                               entry.push(value["ports"]);
-                               tr.entry = entry;
-                               result.push(tr);
-                       });
-                       return result;
-               },
-               popout : function(data) {
-                       var result = [];
-                       $.each(data.nodeData, function(key, value) {
-                               var tr = {};
-                               // fill up all the td's
-                               var entry = [];
-                               var nodenameentry = value["nodeName"] ? value["nodeName"] : "No name provided";
-                               entry.push(nodenameentry);
-                               entry.push(value["nodeId"]);
-                               entry.push(value["tierName"]);
-                               entry.push(value["mac"]);
-                               entry.push(value["ports"]);
-                               entry.push(value["portStatus"]);
-                               tr.entry = entry;
-                               result.push(tr);
-                       });
-                       return result;
-               }
-       }
+                aTag.innerHTML = nodeNameEntry;
+                entry.push(aTag);
+                entry.push(value["nodeId"]);
+                entry.push(value["ports"]);
+                tr.entry = entry;
+                result.push(tr);
+            });
+            return result;
+        },
+        popout : function(data) {
+            var result = [];
+            $.each(data.nodeData, function(key, value) {
+                var tr = {};
+                // fill up all the td's
+                var entry = [];
+                var nodenameentry = value["nodeName"] ? value["nodeName"] : "No name provided";
+                entry.push(nodenameentry);
+                entry.push(value["nodeId"]);
+                entry.push(value["tierName"]);
+                entry.push(value["mac"]);
+                entry.push(value["ports"]);
+                tr.entry = entry;
+                result.push(tr);
+            });
+            return result;
+        }
+    }
 };
 
 one.f.switchmanager.subnetGatewayConfig = {
-       id: {
-               dashlet: {
-                       addIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addIP",
-                       addPorts: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addPorts",
-                       removeIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_removeIP"
-               }, 
-               modal: {
-                       modal: "one_f_switchmanager_subnetGatewayConfig_id_modal_modal",
-                       save: "one_f_switchmanager_subnetGatewayConfig_id_modal_save",
-                       form: {
-                               name : "one_f_switchmanager_subnetGatewayConfig_id_modal_form_gatewayname",
-                               gatewayIPAddress : "one_f_switchmanager_subnetGatewayConfig_id_modal_form_gatewayipaddress",
-                               nodeId: "one_f_switchmanager_subnetGatewayConfig_id_modal_form_nodeid",
-                               ports: "one_f_switchmanager_subnetGatewayConfig_id_modal_form_ports"
-                       }
-               }
-       },
-       // device ajax calls
-       dashlet: function($dashlet) {
-               one.lib.dashlet.empty($dashlet);
-               $dashlet.append(one.lib.dashlet.header(one.f.dashlet.subnetGatewayConfig.name));
-               // Add gateway IP Address button
-               var url = one.f.switchmanager.rootUrl + "/subnets";
-               one.f.switchmanager.subnetGatewayConfig.ajax.main(url, {}, function(content) {
+    id: {
+        dashlet: {
+            addIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addIP",
+            addPorts: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_addPorts",
+            removeIPAddress: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_removeIP",
+            datagrid: "one_f_switchmanager_subnetGatewayConfig_id_dashlet_datagrid"
+        }, 
+        modal: {
+            modal: "one_f_switchmanager_subnetGatewayConfig_id_modal_modal",
+            save: "one_f_switchmanager_subnetGatewayConfig_id_modal_save",
+            form: {
+                name : "one_f_switchmanager_subnetGatewayConfig_id_modal_form_gatewayname",
+                gatewayIPAddress : "one_f_switchmanager_subnetGatewayConfig_id_modal_form_gatewayipaddress",
+                nodeId: "one_f_switchmanager_subnetGatewayConfig_id_modal_form_nodeid",
+                ports: "one_f_switchmanager_subnetGatewayConfig_id_modal_form_ports"
+            }
+        }
+    },
+    // device ajax calls
+    dashlet: function($dashlet) {
+        one.lib.dashlet.empty($dashlet);
+        $dashlet.append(one.lib.dashlet.header(one.f.dashlet.subnetGatewayConfig.name));
+        // Add gateway IP Address button
+        var url = one.f.switchmanager.rootUrl + "/subnets";
+        one.f.switchmanager.subnetGatewayConfig.ajax.main(url, {}, function(content) {
 
             if (content.privilege === 'WRITE') {
                 var button = one.lib.dashlet.button.single("Add Gateway IP Address",
@@ -320,7 +410,7 @@ one.f.switchmanager.subnetGatewayConfig = {
                 $button.click(function() {
                     var requestData = {};
                     var gatewaysToDelete = [];
-                    var checkedCheckBoxes = $("input:checked", $(this).closest(".dashlet").find("table"));
+                    var checkedCheckBoxes = $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).find("tbody input:checked")
                     checkedCheckBoxes.each(function(index, value) {
                         gatewaysToDelete.push(checkedCheckBoxes[index].id);
                     });
@@ -349,263 +439,336 @@ one.f.switchmanager.subnetGatewayConfig = {
                 });
                 $dashlet.append($button);
             }
+            var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid, {
+                searchable: true,
+                filterable: false,
+                pagination: true,
+                flexibleRowsPerPage: true
+                }, "table-striped table-condensed");
+            $dashlet.append($gridHTML);
+            var dataSource = one.f.switchmanager.subnetGatewayConfig.data.devicesgrid(content);
+            $("#" + one.f.switchmanager.subnetGatewayConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource});
+        });
+    },
+    ajax : {
+        main : function(url, requestData, callback) {
+            $.getJSON(url, requestData, function(data) {
+                callback(data);
+            });
+        }
+    },
+    registry: {},
+    modal : {
+        initialize: {
+            gateway: function() {
+                var h3 = "Add Gateway IP Address";
+                var footer = one.f.switchmanager.subnetGatewayConfig.modal.footer();
+                var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.modal, h3, "", footer);
+                // bind save button
+                $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.save, $modal).click(function() {
+                    one.f.switchmanager.subnetGatewayConfig.modal.save.gateway($modal);
+                });
+                var $body = one.f.switchmanager.subnetGatewayConfig.modal.body.gateway();
+                one.lib.modal.inject.body($modal, $body);
+                return $modal;
+            },
+            ports: function() {
+                var h3 = "Add Ports";
+                var footer = one.f.switchmanager.subnetGatewayConfig.modal.footer();
+                var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.modal, h3, "", footer);
+                // bind save button
+                $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.save, $modal).click(function() {
+                    one.f.switchmanager.subnetGatewayConfig.modal.save.ports($modal);
+                });
+                
+                // TODO: Change to subnetGateway instead.
+                one.f.switchmanager.spanPortConfig.modal.ajax.nodes(function(nodes, nodeports) {
+                    var $body = one.f.switchmanager.subnetGatewayConfig.modal.body.ports(nodes, nodeports);
+                    one.lib.modal.inject.body($modal, $body);
+                });
+                return $modal;
+            }
+        },
+        save: {
+            gateway: function($modal) {
+                var result = {};
+                result['gatewayName'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.name, $modal).val();
+                if(!one.f.switchmanager.validateName(result['gatewayName'])) {
+                    alert("Gateway name can contain upto 255 characters");
+                    return;
+                }
+                result['gatewayIPAddress'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.gatewayIPAddress, $modal).val();
+                one.f.switchmanager.subnetGatewayConfig.modal.ajax.gateway(result, 
+                    function(response) {
+                        if(response.status == true) {
+                            $modal.modal('hide');
+                            one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
+                        } else {
+                            alert(response.message);
+                        }
+                    });
+            },
+            ports: function($modal) {
+                var result = {};
+                var gatewayRegistryIndex = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.name, $modal).val();
+                result['portsName'] = one.f.switchmanager.subnetGatewayConfig.registry.gateways[gatewayRegistryIndex];
+                result['nodeId'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.nodeId, $modal).val();
+                result['ports'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports, $modal).val();
+                if(!result['portsName'] || result['portsName'] == "") {
+                    alert("No gateway chosen. Cannot add port");
+                    return;
+                }
+                if(!result['nodeId'] || result['nodeId'] == "") {
+                    alert("Please select a node.");
+                    return;
+                }
+                if(!result['ports'] || result['ports'] == "") {
+                    alert("Please choose a port.");
+                    return;
+                }
+                one.f.switchmanager.subnetGatewayConfig.modal.ajax.ports(result, 
+                    function(response) {
+                        if(response.status == true) {
+                            $modal.modal('hide');
+                            one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
+                        } else {
+                            alert(response.message);
+                        }
+                    });
+            }
+        },
+        body: {
+            gateway: function() {
+                var $form = $(document.createElement('form'));
+                var $fieldset = $(document.createElement('fieldset'));
+                // gateway name
+                var $label = one.lib.form.label("Name");
+                var $input = one.lib.form.input("Name");
+                $input.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.name);
+                $fieldset.append($label).append($input);
+                // gateway IP Mask 
+                var $label = one.lib.form.label("Gateway IP Address/Mask");
+                var $input = one.lib.form.input("Gateway IP Address/Mask");
+                $input.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.gatewayIPAddress);
+                $fieldset.append($label).append($input);
+                
+                $form.append($fieldset);
+                return $form;
+            },
+            ports: function(nodes, nodeports) {
+                var $form = $(document.createElement('form'));
+                var $fieldset = $(document.createElement('fieldset'));
+                // gateways drop down
+                var $label = one.lib.form.label("Gateway Name");
+                var $select = one.lib.form.select.create(one.f.switchmanager.subnetGatewayConfig.registry.gateways);
+                $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.name);
+                $select.val($select.find("option:first").val());
+                $fieldset.append($label).append($select);
 
-                       var body = one.f.switchmanager.subnetGatewayConfig.data.devices(content);
-                       // first column contains checkbox. no need for header
-                       content.columnNames.splice(0,0," ");
-                       var $table = one.f.switchmanager.createTable(content.columnNames, body);
-                       $dashlet.append($table);
-               });
-       },
-       ajax : {
-               main : function(url, requestData, callback) {
-                       $.getJSON(url, requestData, function(data) {
-                               callback(data);
-                       });
-               }
-       },
-       registry: {},
-       modal : {
-               initialize: {
-                       gateway: function() {
-                               var h3 = "Add Gateway IP Address";
-                   var footer = one.f.switchmanager.subnetGatewayConfig.modal.footer();
-                   var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.modal, h3, "", footer);
-                   // bind save button
-                   $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.save, $modal).click(function() {
-                       one.f.switchmanager.subnetGatewayConfig.modal.save.gateway($modal);
-                   });
-                   var $body = one.f.switchmanager.subnetGatewayConfig.modal.body.gateway();
-                   one.lib.modal.inject.body($modal, $body);
-                   return $modal;
-                       },
-                       ports: function() {
-                               var h3 = "Add Ports";
-                   var footer = one.f.switchmanager.subnetGatewayConfig.modal.footer();
-                   var $modal = one.lib.modal.spawn(one.f.switchmanager.subnetGatewayConfig.id.modal.modal, h3, "", footer);
-                   // bind save button
-                   $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.save, $modal).click(function() {
-                       one.f.switchmanager.subnetGatewayConfig.modal.save.ports($modal);
-                   });
-                   
-                   // TODO: Change to subnetGateway instead.
-                   one.f.switchmanager.spanPortConfig.modal.ajax.nodes(function(nodes, nodeports) {
-                       var $body = one.f.switchmanager.subnetGatewayConfig.modal.body.ports(nodes, nodeports);
-                       one.lib.modal.inject.body($modal, $body);
-                   });
-                   return $modal;
-                       }
-               },
-               save: {
-                       gateway: function($modal) {
-                               var result = {};
-                   result['gatewayName'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.name, $modal).val();
-                   if(!one.f.switchmanager.validateName(result['gatewayName'])) {
-                       alert("Gateway name can contain upto 255 characters");
-                       return;
-                   }
-                   result['gatewayIPAddress'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.gatewayIPAddress, $modal).val();
-                   one.f.switchmanager.subnetGatewayConfig.modal.ajax.gateway(result, 
-                                       function(response) {
-                               if(response.status == true) {
-                                       $modal.modal('hide');
-                                       one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
-                               } else {
-                                       alert(response.message);
-                               }
-                           });
-                       },
-                       ports: function($modal) {
-                               var result = {};
-                               var gatewayRegistryIndex = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.name, $modal).val();
-                   result['portsName'] = one.f.switchmanager.subnetGatewayConfig.registry.gateways[gatewayRegistryIndex];
-                   result['nodeId'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.nodeId, $modal).val();
-                   result['ports'] = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports, $modal).val();
-                   if(!result['portsName'] || result['portsName'] == "") {
-                       alert("No gateway chosen. Cannot add port");
-                       return;
-                   }
-                   if(!result['nodeId'] || result['nodeId'] == "") {
-                       alert("Please select a node.");
-                       return;
-                   }
-                   if(!result['ports'] || result['ports'] == "") {
-                       alert("Please choose a port.");
-                       return;
-                   }
-                   one.f.switchmanager.subnetGatewayConfig.modal.ajax.ports(result, 
-                                       function(response) {
-                               if(response.status == true) {
-                                       $modal.modal('hide');
-                                       one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
-                               } else {
-                                       alert(response.message);
-                               }
-                               });
-                       }
-               },
-               body: {
-                       gateway: function() {
-                               var $form = $(document.createElement('form'));
-                               var $fieldset = $(document.createElement('fieldset'));
-                               // gateway name
-                               var $label = one.lib.form.label("Name");
-                               var $input = one.lib.form.input("Name");
-                               $input.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.name);
-                               $fieldset.append($label).append($input);
-                               // gateway IP Mask 
-                               var $label = one.lib.form.label("Gateway IP Address/Mask");
-                               var $input = one.lib.form.input("Gateway IP Address/Mask");
-                               $input.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.gatewayIPAddress);
-                               $fieldset.append($label).append($input);
-                               
-                               $form.append($fieldset);
-                               return $form;
-                       },
-                       ports: function(nodes, nodeports) {
-                               var $form = $(document.createElement('form'));
-                               var $fieldset = $(document.createElement('fieldset'));
-                               // gateways drop down
-                               var $label = one.lib.form.label("Gateway Name");
-                               var $select = one.lib.form.select.create(one.f.switchmanager.subnetGatewayConfig.registry.gateways);
-                               $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.name);
-                               $select.val($select.find("option:first").val());
-                               $fieldset.append($label).append($select);
-
-                               // node ID
-                               var $label = one.lib.form.label("Node ID");
-                               var $select = one.lib.form.select.create(nodes);
-                               $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.nodeId);
-                               one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
-                               $select.val($select.find("option:first").val());
-                               $fieldset.append($label).append($select);
-
-                               // bind onchange
-                               $select.change(function() {
-                                   // retrieve port value
-                                   var node = $(this).find('option:selected').attr('value');
-                                   one.f.switchmanager.subnetGatewayConfig.registry['currentNode'] = node;
-                                   var $ports = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports);
-                                   var ports = nodeports[node];
-                                   one.lib.form.select.inject($ports, ports);
-                                   one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' });
-                                   $ports.val($ports.find("option:first").val());
-                               });
-
-                               // ports
-                               var $label = one.lib.form.label("Select Port");
-                               var $select = one.lib.form.select.create();
-                               $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports);
-                               $fieldset.append($label).append($select);
-                               
-                               $form.append($fieldset);
-                               return $form;
-                       }
-               },
-               ajax: {
-                       gateway: function(requestData, callback) {
-                               $.getJSON(one.f.switchmanager.rootUrl + "/subnetGateway/add", requestData, function(data) {
-                                       callback(data);
-                       });
-                       },
-                       ports: function(requestData, callback) {
-                               $.getJSON(one.f.switchmanager.rootUrl + "/subnetGateway/ports/add", requestData, function(data) {
-                                       callback(data);
-                       });
-                       }
-               },
-               footer : function() {
+                // node ID
+                var $label = one.lib.form.label("Node ID");
+                var $select = one.lib.form.select.create(nodes);
+                $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.nodeId);
+                one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
+                $select.val($select.find("option:first").val());
+                $fieldset.append($label).append($select);
+
+                // bind onchange
+                $select.change(function() {
+                    // retrieve port value
+                    var node = $(this).find('option:selected').attr('value');
+                    one.f.switchmanager.subnetGatewayConfig.registry['currentNode'] = node;
+                    var $ports = $('#' + one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports);
+                    var ports = nodeports[node];
+                    one.lib.form.select.inject($ports, ports);
+                    one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' });
+                    $ports.val($ports.find("option:first").val());
+                });
+
+                // ports
+                var $label = one.lib.form.label("Select Port");
+                var $select = one.lib.form.select.create();
+                $select.attr('id', one.f.switchmanager.subnetGatewayConfig.id.modal.form.ports);
+                $fieldset.append($label).append($select);
+                
+                $form.append($fieldset);
+                return $form;
+            }
+        },
+        ajax: {
+            gateway: function(requestData, callback) {
+                $.getJSON(one.f.switchmanager.rootUrl + "/subnetGateway/add", requestData, function(data) {
+                    callback(data);
+            });
+            },
+            ports: function(requestData, callback) {
+                $.getJSON(one.f.switchmanager.rootUrl + "/subnetGateway/ports/add", requestData, function(data) {
+                    callback(data);
+            });
+            }
+        },
+        footer : function() {
             var footer = [];
             var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.subnetGatewayConfig.id.modal.save, "btn-success", "");
             var $saveButton = one.lib.dashlet.button.button(saveButton);
             footer.push($saveButton);
             return footer;
         }
-       },
-       // data functions
-       data : {
-               devices : function(data) {
-                       var result = [];
-                       one.f.switchmanager.subnetGatewayConfig.registry.gateways = [];
-                       $.each(data.nodeData, function(key, value) {
-                               var tr = {};
-                               // fill up all the td's
-                               var subnetConfigObject = $.parseJSON(value["json"]);
-                               var nodePorts = subnetConfigObject.nodePorts;
-                               var $nodePortsContainer = $(document.createElement("div"));
-                               
-                               for(var i = 0; i < nodePorts.length; i++) {
-                                       var nodePort = nodePorts[i];
-                                       $nodePortsContainer.append(nodePort + " ");
-                                       // add delete anchor tag to delete ports
-                                       var aTag = document.createElement("a");
-                                       aTag.setAttribute("id", encodeURIComponent(nodePort));
-                                       aTag.gatewayName = value["name"];
-                                       aTag.addEventListener("click", function(evt) {
-                                               var htmlPortAnchor = evt.target;
-                                               var requestData = {};
-                                               requestData["gatewayName"] = evt.target.gatewayName;
-                                               requestData["nodePort"] = decodeURIComponent(evt.target.id);
-                                               // make ajax call to delete port
-                                               var url = one.f.switchmanager.rootUrl + "/subnetGateway/ports/delete";
-                                       one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) {
-                                               if(response.status == true) {
-                                                       // refresh dashlet by passing dashlet div as param
-                                       one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
-                                               } else {
-                                                       alert(response.message);
-                                               }
-                                       });
-                                               
-                                       });
-                                       aTag.addEventListener("mouseover", function(evt) {
-                                               evt.target.style.cursor = "pointer";
-                                       }, false);
-                                       aTag.innerHTML = "Delete";
-                                       $nodePortsContainer.append(aTag);
-                                       $nodePortsContainer.append("<br/>");
-                               }
-
-                               // store gateways in the registry so that they can be used in the add ports popup
-                               one.f.switchmanager.subnetGatewayConfig.registry.gateways.push(value["name"]);
-                               var entry = [];
-                               var checkbox = document.createElement("input");
-                               checkbox.setAttribute("type", "checkbox");
-                               checkbox.setAttribute("id", value["name"]);
-                               entry.push(checkbox);
-                               entry.push(value["name"]);
-                               entry.push(value["subnet"]);
-                               entry.push($nodePortsContainer);
-                               tr.entry = entry;
-                               result.push(tr);
-                       });
-                       return result;
-               }
-       }
+    },
+    // data functions
+    data : {
+        devicesgrid: function(data) {
+            one.f.switchmanager.subnetGatewayConfig.registry.gateways = [];
+            var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'selector',
+                            label: ' ',
+                            sortable: false
+                        },
+                        {
+                            property: 'name',
+                            label: 'Name',
+                            sortable: true
+                        },
+                        {
+                            property: 'subnet',
+                            label: 'Gateway IP Address/Mask',
+                            sortable: true
+                        },
+                        {
+                            property: 'json',
+                            label: 'Node/Ports',
+                            sortable: false
+                        }
+                    ],
+                    data: data.nodeData,
+                    formatter: function(items) {
+                        $.each(items, function(index, tableRow) {
+                            tableRow["selector"] = '<input type="checkbox" id=' + tableRow["name"] + '></input>';
+                            var json = tableRow["json"];
+                            var subnetConfigObject = JSON.parse(json);
+                            var nodePortHtml = "<div>";
+                            $.each(subnetConfigObject.nodePorts, function(index, nodePort) {
+                                nodePortHtml += nodePort;
+                                nodePortHtml += "&nbsp;";
+                                nodePortHtml += '<a href="#" id=' + encodeURIComponent(nodePort) + 
+                                    ' gatewayName=' + tableRow["name"] + 
+                                    ' onclick="javascript:one.f.switchmanager.subnetGatewayConfig.actions.deleteNodePort(this);">Delete</a>';
+                                nodePortHtml += "<br/>";
+                            });
+                            nodePortHtml += "</div>";
+                            tableRow["json"] = nodePortHtml;
+                        });
+
+                    },
+                    delay: 0
+                });
+                // populate the registry with subnet names
+                one.f.switchmanager.subnetGatewayConfig.registry.gateways = [];
+                $.each(data.nodeData, function(key, value) {
+                    one.f.switchmanager.subnetGatewayConfig.registry.gateways.push(value["name"]);
+                });
+                return source;          
+        },
+        devices : function(data) {
+            var result = [];
+            one.f.switchmanager.subnetGatewayConfig.registry.gateways = [];
+            $.each(data.nodeData, function(key, value) {
+                var tr = {};
+                // fill up all the td's
+                var subnetConfigObject = $.parseJSON(value["json"]);
+                var nodePorts = subnetConfigObject.nodePorts;
+                var $nodePortsContainer = $(document.createElement("div"));
+                
+                for(var i = 0; i < nodePorts.length; i++) {
+                    var nodePort = nodePorts[i];
+                    $nodePortsContainer.append(nodePort + " ");
+                    // add delete anchor tag to delete ports
+                    var aTag = document.createElement("a");
+                    aTag.setAttribute("id", encodeURIComponent(nodePort));
+                    aTag.gatewayName = value["name"];
+                    aTag.addEventListener("click", function(evt) {
+                        var htmlPortAnchor = evt.target;
+                        var requestData = {};
+                        requestData["gatewayName"] = evt.target.gatewayName;
+                        requestData["nodePort"] = decodeURIComponent(evt.target.id);
+                        // make ajax call to delete port
+                        var url = one.f.switchmanager.rootUrl + "/subnetGateway/ports/delete";
+                        one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) {
+                            if(response.status == true) {
+                                // refresh dashlet by passing dashlet div as param
+                                one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
+                            } else {
+                                alert(response.message);
+                            }
+                        });
+                        
+                    });
+                    aTag.addEventListener("mouseover", function(evt) {
+                        evt.target.style.cursor = "pointer";
+                    }, false);
+                    aTag.innerHTML = "Delete";
+                    $nodePortsContainer.append(aTag);
+                    $nodePortsContainer.append("<br/>");
+                }
+
+                // store gateways in the registry so that they can be used in the add ports popup
+                one.f.switchmanager.subnetGatewayConfig.registry.gateways.push(value["name"]);
+                var entry = [];
+                var checkbox = document.createElement("input");
+                checkbox.setAttribute("type", "checkbox");
+                checkbox.setAttribute("id", value["name"]);
+                entry.push(checkbox);
+                entry.push(value["name"]);
+                entry.push(value["subnet"]);
+                entry.push($nodePortsContainer);
+                tr.entry = entry;
+                result.push(tr);
+            });
+            return result;
+        }
+    },
+    actions: {
+        deleteNodePort: function(htmlPortAnchor) {
+            var requestData = {};
+            requestData["gatewayName"] = htmlPortAnchor.getAttribute("gatewayName");
+            requestData["nodePort"] = decodeURIComponent(htmlPortAnchor.id);
+            // make ajax call to delete port
+            var url = one.f.switchmanager.rootUrl + "/subnetGateway/ports/delete";
+            one.f.switchmanager.subnetGatewayConfig.ajax.main(url, requestData, function(response) {
+                if(response.status == true) {
+                    // refresh dashlet by passing dashlet div as param
+                    one.f.switchmanager.subnetGatewayConfig.dashlet($("#right-bottom .dashlet"));
+                } else {
+                    alert(response.message);
+                }
+            });
+        }
+    }
 }
 
 one.f.switchmanager.staticRouteConfig = {
-       id: {
-               dashlet: {
-                       add: "one_f_switchmanager_staticRouteConfig_id_dashlet_add",
-                       remove: "one_f_switchmanager_staticRouteConfig_id_dashlet_remove"
-               }, 
-               modal: {
-                       modal: "one_f_switchmanager_staticRouteConfig_id_modal_modal",
-                       save: "one_f_switchmanager_staticRouteConfig_id_modal_save",
-                       form: {
-                               routeName : "one_f_switchmanager_staticRouteConfig_id_modal_form_routename",
-                               staticRoute : "one_f_switchmanager_staticRouteConfig_id_modal_form_staticroute",
+    id: {
+        dashlet: {
+            add: "one_f_switchmanager_staticRouteConfig_id_dashlet_add",
+            remove: "one_f_switchmanager_staticRouteConfig_id_dashlet_remove",
+            datagrid: "one_f_switchmanager_staticRouteConfig_id_dashlet_datagrid"
+        }, 
+        modal: {
+            modal: "one_f_switchmanager_staticRouteConfig_id_modal_modal",
+            save: "one_f_switchmanager_staticRouteConfig_id_modal_save",
+            form: {
+                routeName : "one_f_switchmanager_staticRouteConfig_id_modal_form_routename",
+                staticRoute : "one_f_switchmanager_staticRouteConfig_id_modal_form_staticroute",
                 nextHop : "one_f_switchmanager_staticRouteConfig_id_modal_form_nexthop",
-                       }
-               }
-       },
-       dashlet: function($dashlet) {
-               one.lib.dashlet.empty($dashlet);
-               
-
-               var url = one.f.switchmanager.rootUrl + "/staticRoutes";
-               one.f.switchmanager.staticRouteConfig.ajax.main(url, {}, function(content) {
+            }
+        }
+    },
+    dashlet: function($dashlet) {
+        one.lib.dashlet.empty($dashlet);
+        var url = one.f.switchmanager.rootUrl + "/staticRoutes";
+        one.f.switchmanager.staticRouteConfig.ajax.main(url, {}, function(content) {
 
             if (content.privilege === 'WRITE') {
                 // Add static route button
@@ -624,7 +787,8 @@ one.f.switchmanager.staticRouteConfig = {
                 $button.click(function() {
                     var requestData = {};
                     var routesToDelete = [];
-                    var checkedCheckBoxes = $("input:checked", $(this).closest(".dashlet").find("table"));
+                    //var checkedCheckBoxes = $("input:checked", $(this).closest(".dashlet").find("table"));
+                    var checkedCheckBoxes = $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).find("tbody input:checked");
                     checkedCheckBoxes.each(function(index, value) {
                         routesToDelete.push(checkedCheckBoxes[index].id);
                     });
@@ -643,138 +807,176 @@ one.f.switchmanager.staticRouteConfig = {
                 });
                 $dashlet.append($button);
             }
-
-                       var body = one.f.switchmanager.staticRouteConfig.data.staticRouteConfig(content);
-                       // first column contains checkbox. no need for header
-                       content.columnNames.splice(0,0," ");
-                       var tableHeaders = ['', 'Name', 'Static Route', 'Next Hop Address'];
-                       var $table = one.f.switchmanager.createTable(tableHeaders, body);
-                       $dashlet.append($table);
-               });
-       },
-       // device ajax calls
-       ajax : {
-               main : function(url, requestData, callback) {
-                       $.getJSON(url, requestData, function(data) {
-                               callback(data);
-                       });
-               }
-       },
-       registry: {},
-       modal : {
-               initialize: function() {
-                       var h3 = "Add Static Route";
+            var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid, {
+                searchable: true,
+                filterable: false,
+                pagination: true,
+                flexibleRowsPerPage: true
+                }, "table-striped table-condensed");
+            $dashlet.append($gridHTML);
+            var dataSource = one.f.switchmanager.staticRouteConfig.data.staticRouteConfigGrid(content);
+            $("#" + one.f.switchmanager.staticRouteConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource});
+        });
+    },
+    // device ajax calls
+    ajax : {
+        main : function(url, requestData, callback) {
+            $.getJSON(url, requestData, function(data) {
+                callback(data);
+            });
+        }
+    },
+    registry: {},
+    modal : {
+        initialize: function() {
+            var h3 = "Add Static Route";
             var footer = one.f.switchmanager.staticRouteConfig.modal.footer();
             var $modal = one.lib.modal.spawn(one.f.switchmanager.staticRouteConfig.id.modal.modal, h3, "", footer);
             // bind save button
             $('#' + one.f.switchmanager.staticRouteConfig.id.modal.save, $modal).click(function() {
-               one.f.switchmanager.staticRouteConfig.modal.save($modal);
+                one.f.switchmanager.staticRouteConfig.modal.save($modal);
             });
             var $body = one.f.switchmanager.staticRouteConfig.modal.body();
             one.lib.modal.inject.body($modal, $body);
             return $modal;
-               },
-               save: function($modal) {
-                       var result = {};
+        },
+        save: function($modal) {
+            var result = {};
             result['routeName'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.routeName, $modal).val();
             result['staticRoute'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.staticRoute, $modal).val();
             result['nextHop'] = $('#' + one.f.switchmanager.staticRouteConfig.id.modal.form.nextHop, $modal).val();
-                       one.f.switchmanager.staticRouteConfig.modal.ajax.staticRouteConfig(result, function(response) {
-                       if(response.status == true) {
-                               $modal.modal('hide');
-                               // refresh dashlet by passing dashlet div as param
-                               one.f.switchmanager.staticRouteConfig.dashlet($("#left-bottom .dashlet"));
-                       } else {
-                               // TODO: Show error message in a error message label instead.
-                               alert(response.message);
-                       }
-                   });
-               },
-               body: function() {
-                       var $form = $(document.createElement('form'));
-                       var $fieldset = $(document.createElement('fieldset'));
-                       // static route name
-                       var $label = one.lib.form.label("Name");
-                       var $input = one.lib.form.input("Name");
-                       $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.routeName);
-                       $fieldset.append($label).append($input);
-                       // static route IP Mask 
-                       var $label = one.lib.form.label("Static Route");
-                       var $input = one.lib.form.input("Static Route");
-                       $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.staticRoute);
-                       $fieldset.append($label).append($input);
-                       // static route IP Mask 
-                       var $label = one.lib.form.label("Next Hop");
-                       var $input = one.lib.form.input("Next Hop");
-                       $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.nextHop);
-                       $fieldset.append($label).append($input);
-                       // return
-                       $form.append($fieldset);
-                       return $form;
-               },
-               ajax: {
-                       staticRouteConfig: function(requestData, callback) {
-                               $.getJSON(one.f.switchmanager.rootUrl + "/staticRoute/add", requestData, function(data) {
-                                       callback(data);
-                               });
-                       }
-               },
-               data : {
+            one.f.switchmanager.staticRouteConfig.modal.ajax.staticRouteConfig(result, function(response) {
+                    if(response.status == true) {
+                        $modal.modal('hide');
+                        // refresh dashlet by passing dashlet div as param
+                        one.f.switchmanager.staticRouteConfig.dashlet($("#left-bottom .dashlet"));
+                    } else {
+                        // TODO: Show error message in a error message label instead.
+                        alert(response.message);
+                    }
+                });
+        },
+        body: function() {
+            var $form = $(document.createElement('form'));
+            var $fieldset = $(document.createElement('fieldset'));
+            // static route name
+            var $label = one.lib.form.label("Name");
+            var $input = one.lib.form.input("Name");
+            $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.routeName);
+            $fieldset.append($label).append($input);
+            // static route IP Mask 
+            var $label = one.lib.form.label("Static Route");
+            var $input = one.lib.form.input("Static Route");
+            $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.staticRoute);
+            $fieldset.append($label).append($input);
+            // static route IP Mask 
+            var $label = one.lib.form.label("Next Hop");
+            var $input = one.lib.form.input("Next Hop");
+            $input.attr('id', one.f.switchmanager.staticRouteConfig.id.modal.form.nextHop);
+            $fieldset.append($label).append($input);
+            // return
+            $form.append($fieldset);
+            return $form;
+        },
+        ajax: {
+            staticRouteConfig: function(requestData, callback) {
+                $.getJSON(one.f.switchmanager.rootUrl + "/staticRoute/add", requestData, function(data) {
+                    callback(data);
+                });
+            }
+        },
+        data : {
             
         },
-               footer : function() {
+        footer : function() {
             var footer = [];
             var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.staticRouteConfig.id.modal.save, "btn-success", "");
             var $saveButton = one.lib.dashlet.button.button(saveButton);
             footer.push($saveButton);
             return footer;
         }
-       },
-       // data functions
-       data : {
-               staticRouteConfig : function(data) {
-                       var result = [];
-                       $.each(data.nodeData, function(key, value) {
-                               var tr = {};
-                               // fill up all the td's
-                               var entry = [];
-                               var checkbox = document.createElement("input");
-                               checkbox.setAttribute("type", "checkbox");
-                               checkbox.setAttribute("id", value["name"]);
-                               entry.push(checkbox);
-                               entry.push(value["name"]);
-                               entry.push(value["staticRoute"]);
-                               entry.push(value["nextHop"]);
-                               tr.entry = entry;
-                               result.push(tr);
-                       });
-                       return result;
-               }
-       }
+    },
+    // data functions
+    data : {
+        staticRouteConfigGrid: function(data) {
+            var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'selector',
+                            label: ' ',
+                            sortable: false
+                        },
+                        {
+                            property: 'name',
+                            label: 'Name',
+                            sortable: true
+                        },
+                        {
+                            property: 'staticRoute',
+                            label: 'Static Route',
+                            sortable: true
+                        },
+                        {
+                            property: 'nextHop',
+                            label: 'Next Hop Address',
+                            sortable: true
+                        }
+                    ],
+                    data: data.nodeData,
+                    formatter: function(items) {
+                        $.each(items, function(index, item) {
+                            item["selector"] = '<input type="checkbox" id=' + item["name"] + '></input>';
+                        });
+
+                    },
+                    delay: 0
+                });
+            return source;              
+        },
+        staticRouteConfig : function(data) {
+            var result = [];
+            $.each(data.nodeData, function(key, value) {
+                var tr = {};
+                // fill up all the td's
+                var entry = [];
+                var checkbox = document.createElement("input");
+                checkbox.setAttribute("type", "checkbox");
+                checkbox.setAttribute("id", value["name"]);
+                entry.push(checkbox);
+                entry.push(value["name"]);
+                entry.push(value["staticRoute"]);
+                entry.push(value["nextHop"]);
+                tr.entry = entry;
+                result.push(tr);
+            });
+            return result;
+        }
+    }
 }
 
 one.f.switchmanager.spanPortConfig = {
-       id: {
-               dashlet: {
-                       add: "one_f_switchmanager_spanPortConfig_id_dashlet_add",
-                       remove: "one_f_switchmanager_spanPortConfig_id_dashlet_remove"
-               }, 
-               modal: {
-                       modal: "one_f_switchmanager_spanPortConfig_id_modal_modal",
-                       save: "one_f_switchmanager_spanPortConfig_id_modal_save",
-                       form: {
-                               name : "one_f_switchmanager_spanPortConfig_id_modal_form_name",
-                               nodes : "one_f_switchmanager_spanPortConfig_id_modal_form_nodes",
+    id: {
+        dashlet: {
+            add: "one_f_switchmanager_spanPortConfig_id_dashlet_add",
+            remove: "one_f_switchmanager_spanPortConfig_id_dashlet_remove",
+            datagrid: "one_f_switchmanager_spanPortConfig_id_dashlet_datagrid"
+        }, 
+        modal: {
+            modal: "one_f_switchmanager_spanPortConfig_id_modal_modal",
+            save: "one_f_switchmanager_spanPortConfig_id_modal_save",
+            form: {
+                name : "one_f_switchmanager_spanPortConfig_id_modal_form_name",
+                nodes : "one_f_switchmanager_spanPortConfig_id_modal_form_nodes",
                 port : "one_f_switchmanager_spanPortConfig_id_modal_form_port",
-                       }
-               }
-       },
-       dashlet: function($dashlet) {
-               one.lib.dashlet.empty($dashlet);
+            }
+        }
+    },
+    dashlet: function($dashlet) {
+        one.lib.dashlet.empty($dashlet);
         
         //populate table in dashlet
-               var url = one.f.switchmanager.rootUrl + "/spanPorts";
-               one.f.switchmanager.spanPortConfig.ajax.main(url, {}, function(content) {
+        var url = one.f.switchmanager.rootUrl + "/spanPorts";
+        one.f.switchmanager.spanPortConfig.ajax.main(url, {}, function(content) {
 
             if (content.privilege === 'WRITE') {
 
@@ -794,11 +996,11 @@ one.f.switchmanager.spanPortConfig = {
                 var $button = one.lib.dashlet.button.button(button);
                 $button.click(function() {
 
-                    var checkedCheckBoxes = $("input:checked", $(this).closest(".dashlet").find("table"));
+                    var checkedCheckBoxes = $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).find("tbody input:checked");
                     if (checkedCheckBoxes.length > 0) {
                         var spanPortsToDelete = "";
                         checkedCheckBoxes.each(function(index, value) {
-                            spanPortsToDelete += checkedCheckBoxes[index].spanPort + "###";
+                            spanPortsToDelete += decodeURIComponent(checkedCheckBoxes[index].getAttribute("spanPort")) + "###";
                         });
 
                         var requestData = {};
@@ -816,31 +1018,37 @@ one.f.switchmanager.spanPortConfig = {
                 });
                 $dashlet.append($button);
             }
+            var $gridHTML = one.lib.dashlet.datagrid.init(one.f.switchmanager.spanPortConfig.id.dashlet.datagrid, {
+                searchable: true,
+                filterable: false,
+                pagination: true,
+                flexibleRowsPerPage: true
+                }, "table-striped table-condensed");
+            $dashlet.append($gridHTML);
+            var dataSource = one.f.switchmanager.spanPortConfig.data.spanPortConfigGrid(content);
+            $("#" + one.f.switchmanager.spanPortConfig.id.dashlet.datagrid).datagrid({dataSource: dataSource});
+
+
 
-                       var body = one.f.switchmanager.spanPortConfig.data.devices(content);
-                       // first column contains the checkbox. no header required.
-                       content.columnNames.splice(0,0," ");
-                       var $table = one.f.switchmanager.createTable(content.columnNames, body);
-                       $dashlet.append($table);
-               });
-       },
-       // device ajax calls
-       ajax : {
-               main : function(url, requestData, callback) {
-                       $.getJSON(url, requestData, function(data) {
-                               callback(data);
-                       });
-               }
-       },
-       registry: {},
-       modal : {
-               initialize: function() {
-                       var h3 = "Add SPAN Port";
+        });
+    },
+    // device ajax calls
+    ajax : {
+        main : function(url, requestData, callback) {
+            $.getJSON(url, requestData, function(data) {
+                callback(data);
+            });
+        }
+    },
+    registry: {},
+    modal : {
+        initialize: function() {
+            var h3 = "Add SPAN Port";
             var footer = one.f.switchmanager.spanPortConfig.modal.footer();
             var $modal = one.lib.modal.spawn(one.f.switchmanager.spanPortConfig.id.modal.modal, h3, "", footer);
             // bind save button
             $('#' + one.f.switchmanager.spanPortConfig.id.modal.save, $modal).click(function() {
-               one.f.switchmanager.spanPortConfig.modal.save($modal);
+                one.f.switchmanager.spanPortConfig.modal.save($modal);
             });
 
             one.f.switchmanager.spanPortConfig.modal.ajax.nodes(function(nodes, nodeports) {
@@ -848,70 +1056,70 @@ one.f.switchmanager.spanPortConfig = {
                 one.lib.modal.inject.body($modal, $body);
             });
             return $modal;
-               },
-               save: function($modal) {
-                       var result = {};
+        },
+        save: function($modal) {
+            var result = {};
             result['nodeId'] = $('#' + one.f.switchmanager.spanPortConfig.id.modal.form.nodes, $modal).val();
             result['spanPort'] = $('#' + one.f.switchmanager.spanPortConfig.id.modal.form.port, $modal).val();
-                       one.f.switchmanager.spanPortConfig.modal.ajax.saveSpanPortConfig(result, 
-                               function(response) {
-                                       if(response.status == true) {
-                                               $modal.modal('hide');
-                                               one.f.switchmanager.spanPortConfig.dashlet($("#right-bottom .dashlet"));
-                                       } else {
-                                               alert(response.message);
-                                       }
-                       
-                   });
-               },
-               body: function(nodes, nodeports) {
-                       var $form = $(document.createElement('form'));
-                       var $fieldset = $(document.createElement('fieldset'));
-                       // node
-                       var $label = one.lib.form.label("Node");
-                       var $select = one.lib.form.select.create(nodes);
-                       one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
-                       $select.attr('id', one.f.switchmanager.spanPortConfig.id.modal.form.nodes);
-                       
-                       // bind onchange
-                       $select.change(function() {
-                           // retrieve port value
-                           var node = $(this).find('option:selected').attr('value');
-                           one.f.switchmanager.spanPortConfig.registry['currentNode'] = node;
-                           var $ports = $('#' + one.f.switchmanager.spanPortConfig.id.modal.form.port);
-                           var ports = nodeports[node];
-                           one.lib.form.select.inject($ports, ports);
-                       });
+            one.f.switchmanager.spanPortConfig.modal.ajax.saveSpanPortConfig(result, 
+                function(response) {
+                    if(response.status == true) {
+                        $modal.modal('hide');
+                        one.f.switchmanager.spanPortConfig.dashlet($("#right-bottom .dashlet"));
+                    } else {
+                        alert(response.message);
+                    }
+                    
+                });
+        },
+        body: function(nodes, nodeports) {
+            var $form = $(document.createElement('form'));
+            var $fieldset = $(document.createElement('fieldset'));
+            // node
+            var $label = one.lib.form.label("Node");
+            var $select = one.lib.form.select.create(nodes);
+            one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
+            $select.attr('id', one.f.switchmanager.spanPortConfig.id.modal.form.nodes);
+            
+            // bind onchange
+            $select.change(function() {
+                // retrieve port value
+                var node = $(this).find('option:selected').attr('value');
+                one.f.switchmanager.spanPortConfig.registry['currentNode'] = node;
+                var $ports = $('#' + one.f.switchmanager.spanPortConfig.id.modal.form.port);
+                var ports = nodeports[node];
+                one.lib.form.select.inject($ports, ports);
+            });
 
             $fieldset.append($label).append($select);
-                       // input port
-                       var $label = one.lib.form.label("Input Port");
-                       var $select = one.lib.form.select.create();
-                       $select.attr('id', one.f.switchmanager.spanPortConfig.id.modal.form.port);
-                       $fieldset.append($label).append($select);
-                       
-                       // return
-                       $form.append($fieldset);
-                       return $form;
-               },
-               ajax: {
-                       nodes: function(callback) {
-                               $.getJSON(one.f.switchmanager.rootUrl + "/nodeports", function(data) {
+            // input port
+            var $label = one.lib.form.label("Input Port");
+            var $select = one.lib.form.select.create();
+            $select.attr('id', one.f.switchmanager.spanPortConfig.id.modal.form.port);
+            $fieldset.append($label).append($select);
+            
+            // return
+            $form.append($fieldset);
+            return $form;
+        },
+        ajax: {
+            nodes: function(callback) {
+                $.getJSON(one.f.switchmanager.rootUrl + "/nodeports", function(data) {
                     var nodes = one.f.switchmanager.spanPortConfig.modal.data.nodes(data);
                     var nodeports = data;
                     one.f.switchmanager.spanPortConfig.registry['nodeports'] = nodeports;
                     callback(nodes, nodeports);
                 });
-                       },
-                       saveSpanPortConfig: function(requestData, callback) {
-                               var resource = {};
-                               resource["jsonData"] = JSON.stringify(requestData);
-                               $.getJSON(one.f.switchmanager.rootUrl + "/spanPorts/add", resource, function(data) {
-                                       callback(data);
-                               });
-                       }
-               },
-               data : {
+            },
+            saveSpanPortConfig: function(requestData, callback) {
+                var resource = {};
+                resource["jsonData"] = JSON.stringify(requestData);
+                $.getJSON(one.f.switchmanager.rootUrl + "/spanPorts/add", resource, function(data) {
+                    callback(data);
+                });
+            }
+        },
+        data : {
             nodes : function(data) {
                 result = {};
                 $.each(data, function(key, value) {
@@ -920,34 +1128,63 @@ one.f.switchmanager.spanPortConfig = {
                 return result;
             }
         },
-               footer : function() {
+        footer : function() {
             var footer = [];
             var saveButton = one.lib.dashlet.button.single("Save", one.f.switchmanager.spanPortConfig.id.modal.save, "btn-success", "");
             var $saveButton = one.lib.dashlet.button.button(saveButton);
             footer.push($saveButton);
             return footer;
         }
-       },
-       // data functions
-       data : {
-               devices : function(data) {
-                       var result = [];
-                       $.each(data.nodeData, function(key, value) {
-                               var tr = {};
-                               // fill up all the td's
-                               var entry = [];
-                               var checkbox = document.createElement("input");
-                               checkbox.setAttribute("type", "checkbox");
-                               checkbox.spanPort = value.json;
-                               entry.push(checkbox);
-                               entry.push(value["nodeName"]);
-                               entry.push(value["spanPort"]);
-                               tr.entry = entry;
-                               result.push(tr);
-                       });
-                       return result;
-               }
-       }
+    },
+    // data functions
+    data : {
+        spanPortConfigGrid: function(data) {
+            var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'selector',
+                            label: ' ',
+                            sortable: false
+                        },
+                        {
+                            property: 'nodeName',
+                            label: 'Node',
+                            sortable: true
+                        },
+                        {
+                            property: 'spanPort',
+                            label: 'span Port',
+                            sortable: true
+                        },
+                    ],
+                    data: data.nodeData,
+                    formatter: function(items) {
+                        $.each(items, function(index, item) {
+                            item["selector"] = '<input type="checkbox" spanPort=' + encodeURIComponent(item["json"]) + '></input>';
+                        });
+                    },
+                    delay: 0
+                });
+            return source;              
+        },
+        devices : function(data) {
+            var result = [];
+            $.each(data.nodeData, function(key, value) {
+                var tr = {};
+                // fill up all the td's
+                var entry = [];
+                var checkbox = document.createElement("input");
+                checkbox.setAttribute("type", "checkbox");
+                checkbox.spanPort = value.json;
+                entry.push(checkbox);
+                entry.push(value["nodeName"]);
+                entry.push(value["spanPort"]);
+                tr.entry = entry;
+                result.push(tr);
+            });
+            return result;
+        }
+    }
 }
 
 /** INIT **/
@@ -968,20 +1205,27 @@ $(one.f.menu.right.bottom).each(function(index, value) {
 });
 
 one.f.addPopOut = function() {
-       $img1 = $(document.createElement("img"));
-       $img1.attr("src", "/img/Expand16T.png");
-       $img1.attr("style", "float: right;");
-       $img1.hover(function() {
-               $img1.css("cursor", "pointer");
-       });
-       $img1.click(function() {
-               var $modal = one.f.switchmanager.nodesLearnt.modal.initialize.popout();
-       $modal.css('width', 'auto');
-               $modal.css('margin-left', '-40%');
+    $img1 = $(document.createElement("img"));
+    $img1.attr("src", "/img/Expand16T.png");
+    $img1.attr("style", "float: right;");
+    $img1.hover(function() {
+        $img1.css("cursor", "pointer");
+    });
+    $img1.click(function() {
+        var $modal = one.f.switchmanager.nodesLearnt.modal.initialize.popout();
+        $modal.css({
+            'margin-left': '-45%',
+            'margin-top': '-3%',
+            'width':$(document).width() * 0.8,
+            'height':$(document).height() * 0.9
+        });
+        $(".modal-body", $modal).css({
+            "max-height": $(document).height() * 0.75,
+        });
         $modal.modal();
-       });
-       $dash1 = $($("#left-top .nav")[0]);
-       $dash1.append($img1);
+    });
+    $dash1 = $($("#left-top .nav")[0]);
+    $dash1.append($img1);
 };
 one.f.addPopOut();
 
@@ -1001,16 +1245,16 @@ $('.dash .nav a', '#main').click(function() {
     var menu = one.f.dashlet;
     switch (id) {
         case menu.nodesLearnt.id:
-               one.f.switchmanager.nodesLearnt.dashlet($dashlet);
+            one.f.switchmanager.nodesLearnt.dashlet($dashlet);
             break;
         case menu.staticRouteConfig.id:
-               one.f.switchmanager.staticRouteConfig.dashlet($dashlet);
+            one.f.switchmanager.staticRouteConfig.dashlet($dashlet);
             break;
         case menu.subnetGatewayConfig.id:
-               one.f.switchmanager.subnetGatewayConfig.dashlet($dashlet);
+            one.f.switchmanager.subnetGatewayConfig.dashlet($dashlet);
             break;
         case menu.spanPortConfig.id:
-               one.f.switchmanager.spanPortConfig.dashlet($dashlet);
+            one.f.switchmanager.spanPortConfig.dashlet($dashlet);
             break;
     };
 });
index 4396c957bf86f96f37c8784967bc4b605f2196a7..9444360eecb7d7ae4a6e084a4fde8512c7b5ed71 100644 (file)
@@ -47,6 +47,7 @@ import com.google.gson.Gson;
 public class Flows implements IDaylightWeb {
     private static final UserLevel AUTH_LEVEL = UserLevel.CONTAINERUSER;
     private static final String WEB_NAME = "Flows";
+
     private static final String WEB_ID = "flows";
     private static final short WEB_ORDER = 2;
 
@@ -237,6 +238,7 @@ public class Flows implements IDaylightWeb {
         Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
         if (action.equals("add")) {
             result = frm.addStaticFlow(flow);
+            DaylightWebUtil.auditlog("Flow", userName, "added", flow.getName(), containerName);
         }
 
         return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result
@@ -270,8 +272,14 @@ public class Flows implements IDaylightWeb {
         }
         if (action.equals("remove")) {
             result = frm.removeStaticFlow(name, node);
+            if(result.isSuccess()) {
+                DaylightWebUtil.auditlog("Flow", userName, "removed", name, containerName);
+            }
         } else if (action.equals("toggle")) {
             result = frm.toggleStaticFlowStatus(name, node);
+            if(result.isSuccess()) {
+                DaylightWebUtil.auditlog("Flow", userName, "toggled", name, containerName);
+            }
         } else {
             result = new Status(StatusCode.BADREQUEST, "Unknown action");
         }
index 7ff54ed4dca511a6e4ba1238b1b962e004efd261..2a2dbf5b4d1b0dc38e5c87bb4463d53eefd9ee21 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
  *
@@ -47,7 +46,7 @@ one.f.address = {
     root : "/controller/web/flows",
     flows : {
         main : "/main",
-               flows : "/node-flows",
+        flows : "/node-flows",
         nodes : "/node-ports",
         flow : "/flow"
     }
@@ -55,54 +54,63 @@ one.f.address = {
 
 /** NODES **/
 one.f.nodes = {
-    id : {},
+    id : {
+        dashlet: {
+            datagrid: "one_f_nodes_id_dashlet_datagrid"
+        }
+    },
     registry : {},
     dashlet : function($dashlet) {
         var $h4 = one.lib.dashlet.header("Nodes");
         $dashlet.append($h4);
 
-        // load body
-        one.f.nodes.ajax.dashlet(function($table) {
-                       // total nodes count
-                       var nodeCount = $table.find('tbody').find('tr').size();
-                       // prompt output
-                       var nodeText = "node";
-                       var verb = "is";
-                       if (nodeCount != 1) {
-                               nodeText += "s";
-                               verb = "are";
-                       }
-                       var out = "There "+verb+" "+nodeCount+" "+nodeText;
-                       $p = $(document.createElement('p'));
-                       $p.append(out);
-                       $dashlet.append($p);
-            // add to dashlet
-            $dashlet.append($table);
+        one.f.nodes.ajax.dashlet(function(data) {
+            var $gridHTML = one.lib.dashlet.datagrid.init(one.f.nodes.id.dashlet.datagrid, {
+                searchable: true,
+                filterable: false,
+                pagination: true,
+                flexibleRowsPerPage: true
+                }, "table-striped table-condensed");
+            $dashlet.append($gridHTML);
+            var dataSource = one.f.nodes.data.nodesDataGrid(data);
+            $("#" + one.f.nodes.id.dashlet.datagrid).datagrid({dataSource: dataSource});
         });
     },
     ajax : {
         dashlet : function(callback) {
             $.getJSON(one.f.address.root+one.f.address.flows.flows, function(data) {
-                var body = one.f.nodes.data.dashlet(data);
-                var $body = one.f.nodes.body.dashlet(body, callback);
-                callback($body);
+                callback(data);
             });
         }
     },
     data : {
-        dashlet : function(data) {
-            var body = [];
-            $.each(data, function(key, value) {
-                var tr = {};
-                var entry = [];
-                entry.push(key);
-                // parse ports
-                entry.push(value);
-                // add entry to tr
-                tr['entry'] = entry;
-                body.push(tr);
+        nodesDataGrid: function(data) {
+            var gridData = [];
+            $.each(data, function(nodeName, flow) {
+                var nodeFlowObject = {};
+                nodeFlowObject["nodeName"] = nodeName;
+                nodeFlowObject["flows"] = flow;
+                nodeFlowObject["rowData"] = nodeName + flow + "-foobar";
+                gridData.push(nodeFlowObject);
             });
-            return body;
+
+            var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'nodeName',
+                            label: 'Node',
+                            sortable: true
+                        },
+                        {
+                            property: 'flows',
+                            label: 'Flows',
+                            sortable: true
+                        }
+                    ],
+                    data: gridData,
+                    delay: 0
+                });
+            return source;
         }
     },
     body : {
@@ -132,109 +140,109 @@ one.f.detail = {
 
         // details
         if (details == undefined) {
-               var $none = $(document.createElement('div'));
-               $none.addClass('none');
+            var $none = $(document.createElement('div'));
+            $none.addClass('none');
             var $p = $(document.createElement('p'));
             $p.text('Please select a flow');
             $p.addClass('text-center').addClass('text-info');
 
             $dashlet.append($none)
-               .append($p);
+                .append($p);
         }
     },
     data : {
-               dashlet : function(data) {
-                       var body = [];
-                       var tr = {};
-                       var entry = [];
-
-                       entry.push(data['name']);
-                       entry.push(data['node']);
-                       entry.push(data['flow']['priority']);
-                       entry.push(data['flow']['hardTimeout']);
-                       entry.push(data['flow']['idleTimeout']);
-
-                       tr.entry = entry;
-                       body.push(tr);
-                       return body;
-               },
+        dashlet : function(data) {
+            var body = [];
+            var tr = {};
+            var entry = [];
+
+            entry.push(data['name']);
+            entry.push(data['node']);
+            entry.push(data['flow']['priority']);
+            entry.push(data['flow']['hardTimeout']);
+            entry.push(data['flow']['idleTimeout']);
+
+            tr.entry = entry;
+            body.push(tr);
+            return body;
+        },
         description : function(data) {
-                       var body = [];
-                       var tr = {};
-                       var entry = [];
+            var body = [];
+            var tr = {};
+            var entry = [];
                         entry.push(data['flow']['ingressPort']);
-                       entry.push(data['flow']['etherType']);
-                       entry.push(data['flow']['vlanId']);
-                       entry.push(data['flow']['vlanPriority']);
-                       entry.push(data['flow']['srcMac']);
-                       entry.push(data['flow']['dstMac']);
-                       entry.push(data['flow']['srcIp']);
-                       entry.push(data['flow']['dstIp']);
-                       entry.push(data['flow']['tosBits']);
-                       entry.push(data['flow']['srcPort']);
-                       entry.push(data['flow']['dstPort']);
-                       entry.push(data['flow']['protocol']);
-                       entry.push(data['flow']['cookie']);
-
-                       tr.entry = entry;
-                       body.push(tr);
-                       return body;
+            entry.push(data['flow']['etherType']);
+            entry.push(data['flow']['vlanId']);
+            entry.push(data['flow']['vlanPriority']);
+            entry.push(data['flow']['srcMac']);
+            entry.push(data['flow']['dstMac']);
+            entry.push(data['flow']['srcIp']);
+            entry.push(data['flow']['dstIp']);
+            entry.push(data['flow']['tosBits']);
+            entry.push(data['flow']['srcPort']);
+            entry.push(data['flow']['dstPort']);
+            entry.push(data['flow']['protocol']);
+            entry.push(data['flow']['cookie']);
+
+            tr.entry = entry;
+            body.push(tr);
+            return body;
         },
-               actions : function(data) {
-                       var body = [];
-                       var tr = {};
-                       var entry = [];
-
-                       var actions = '';
-                       $(data['flow']['actions']).each(function(index, value) {
-                               actions += value + ', ';
-                       });
-                       actions = actions.slice(0,-2);
-                       entry.push(actions);
-
-                       tr.entry = entry;
-                       body.push(tr);
-                       return body;
-               }
+        actions : function(data) {
+            var body = [];
+            var tr = {};
+            var entry = [];
+
+            var actions = '';
+            $(data['flow']['actions']).each(function(index, value) {
+                actions += value + ', ';
+            });
+            actions = actions.slice(0,-2);
+            entry.push(actions);
+
+            tr.entry = entry;
+            body.push(tr);
+            return body;
+        }
     },
     body : {
         dashlet : function(body) {
-                       // create table
-                       var header = ['Flow Name', 'Node', 'Priority', 'Hard Timeout', 'Idle Timeout'];
-                       var $thead = one.lib.dashlet.table.header(header);
-                       var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
-                       var $table = one.lib.dashlet.table.table(attributes);
-                       $table.append($thead);
+            // create table
+            var header = ['Flow Name', 'Node', 'Priority', 'Hard Timeout', 'Idle Timeout'];
+            var $thead = one.lib.dashlet.table.header(header);
+            var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
+            var $table = one.lib.dashlet.table.table(attributes);
+            $table.append($thead);
 
-                       var $tbody = one.lib.dashlet.table.body(body);
-                       $table.append($tbody);
+            var $tbody = one.lib.dashlet.table.body(body);
+            $table.append($tbody);
 
             return $table;
         },
-               description : function(body) {
-                       var header = ['Input Port', 'Ethernet Type', 'VLAN ID', 'VLAN Priority', 'Source MAC', 'Dest MAC', 'Source IP', 'Dest IP', 'TOS', 'Source Port', 'Dest Port', 'Protocol', 'Cookie'];
-                       var $thead = one.lib.dashlet.table.header(header);
-                       var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
-                       var $table = one.lib.dashlet.table.table(attributes);
-                       $table.append($thead);
+        description : function(body) {
+            var header = ['Input Port', 'Ethernet Type', 'VLAN ID', 'VLAN Priority', 'Source MAC', 'Dest MAC', 'Source IP', 'Dest IP', 'TOS', 'Source Port', 'Dest Port', 'Protocol', 'Cookie'];
+            var $thead = one.lib.dashlet.table.header(header);
+            var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
+            var $table = one.lib.dashlet.table.table(attributes);
+            $table.append($thead);
 
-                       var $tbody = one.lib.dashlet.table.body(body);
-                       $table.append($tbody);
+            var $tbody = one.lib.dashlet.table.body(body);
+            $table.append($tbody);
 
             return $table;
-               },
-               actions : function(body) {
-                       var header = ['Actions'];
-                       var $thead = one.lib.dashlet.table.header(header);
-                       var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
-                       var $table = one.lib.dashlet.table.table(attributes);
-                       $table.append($thead);
+        },
+        actions : function(body) {
+            var header = ['Actions'];
+            var $thead = one.lib.dashlet.table.header(header);
+            var attributes = ['table-striped', 'table-bordered', 'table-condensed'];
+            var $table = one.lib.dashlet.table.table(attributes);
+            $table.append($thead);
 
-                       var $tbody = one.lib.dashlet.table.body(body);
-                       $table.append($tbody);
+            var $tbody = one.lib.dashlet.table.body(body);
+            $table.append($tbody);
 
             return $table;
-               }
+        }
     }
 }
 
@@ -244,15 +252,16 @@ one.f.flows = {
         dashlet : {
             add : "one_f_flows_id_dashlet_add",
             remove : "one_f_flows_id_dashlet_remove",
-            toggle : "one_f_flows_id_dashlet_toggle"
+            toggle : "one_f_flows_id_dashlet_toggle",
+            datagrid: "one_f_flows_id_dashlet_datagrid"
         },
         modal : {
-                       install : "one_f_flows_id_modal_install",
+            install : "one_f_flows_id_modal_install",
             add : "one_f_flows_id_modal_add",
             close : "one_f_flows_id_modal_close",
             modal : "one_f_flows_id_modal_modal",
             dialog : {
-               modal : "one_f_flows_id_modal_dialog_modal",
+                modal : "one_f_flows_id_modal_dialog_modal",
                 remove : "one_f_flows_id_modal_dialog_remove",
                 close : "one_f_flows_id_modal_dialog_close"
             },
@@ -272,11 +281,11 @@ one.f.flows = {
                 modifyTosBits : "one_f_flows_modal_action_modifyTosBits",
                 modifyTransportSourcePort : "one_f_flows_modal_action_modifyTransportSourcePort",
                 modifyTransportDestinationPort : "one_f_flows_modal_action_modifyTransportDestinationPort",
-                               modal : {
-                                       modal : "one_f_flows_modal_action_modal_modal",
-                                       remove : "one_f_flows_modal_action_modal_remove",
-                                       cancel : "one_f_flows_modal_action_modal_cancel"
-                               }
+                modal : {
+                    modal : "one_f_flows_modal_action_modal_modal",
+                    remove : "one_f_flows_modal_action_modal_remove",
+                    cancel : "one_f_flows_modal_action_modal_cancel"
+                }
             },
             form : {
                 name : "one_f_flows_id_modal_form_name",
@@ -284,8 +293,8 @@ one.f.flows = {
                 port : "one_f_flows_id_modal_form_port",
                 priority : "one_f_flows_id_modal_form_priority",
                 hardTimeout : "one_f_flows_id_modal_form_hardTimeout",
-                               idleTimeout : "one_f_flows_id_modal_form_idleTimeout",
-                               cookie : "one_f_flows_id_modal_form_cookie",
+                idleTimeout : "one_f_flows_id_modal_form_idleTimeout",
+                cookie : "one_f_flows_id_modal_form_cookie",
                 etherType : "one_f_flows_id_modal_form_etherType",
                 vlanId : "one_f_flows_id_modal_form_vlanId",
                 vlanPriority : "one_f_flows_id_modal_form_vlanPriority",
@@ -304,7 +313,7 @@ one.f.flows = {
     dashlet : function($dashlet, callback) {
 
         // load body
-        one.f.flows.ajax.dashlet(function($table) {
+        one.f.flows.ajax.dashlet(function(data) {
 
             var $h4 = one.lib.dashlet.header("Flow Entries");
 
@@ -321,28 +330,39 @@ one.f.flows = {
 
             }
 
-            // table bindings
-            $table.find('tbody').find('tr').click(function() {
-                var id = $($(this).find('td')[0]).text();
-                var node = $(this).data('id');
-                one.f.flows.detail(id, node);
+            var $gridHTML = one.lib.dashlet.datagrid.init(one.f.flows.id.dashlet.datagrid, {
+                searchable: true,
+                filterable: false,
+                pagination: true,
+                flexibleRowsPerPage: true
+                }, "table-striped table-condensed");
+            $dashlet.append($gridHTML);
+            var dataSource = one.f.flows.data.flowsDataGrid(data);
+            $("#" + one.f.flows.id.dashlet.datagrid).datagrid({dataSource: dataSource}).on("loaded", function() {
+                $("#" + one.f.flows.id.dashlet.datagrid).find("tbody tr").each(function(index, tr) {
+                    $tr = $(tr);
+                    $span = $("td span", $tr);
+                    var flowstatus = $span.data("flowstatus");
+                    var installInHw = $span.data("installinhw").toString();
+                    if(installInHw == "true" && flowstatus == "Success") {
+                        $tr.addClass("success");
+                    } else {
+                        $tr.addClass("warning");
+                    }
+                    // attach mouseover to show pointer cursor
+                    $tr.mouseover(function() {
+                        $(this).css("cursor", "pointer");
+                    });
+                    // attach click event
+                    $tr.click(function() {
+                        var $td = $($(this).find("td")[0]);
+                        var id = $td.text();
+                        var node = $td.find("span").data("nodeid");
+                        one.f.flows.detail(id, node);   
+                    });
+                });
             });
-
-                       // total flows
-                       var flowCount = $table.find('tbody').find('tr').size();
-                       // prompt output
-                       var flowText = "flow";
-                       var verb = "is";
-                       if (flowCount != 1) {
-                               flowText += "s";
-                               verb = "are";
-                       }
-                       var out = "There "+verb+" "+flowCount+" "+flowText;
-                       $p = $(document.createElement('p'));
-                       $p.append(out);
-                       $dashlet.append($p);
-            // add table to dashlet
-            $dashlet.append($table);
+            
             // details callback
             if(callback != undefined) callback();
         });
@@ -363,54 +383,54 @@ one.f.flows = {
             }
         });
         if (one.f.flows.registry.privilege === 'WRITE') {
-               // remove button
-               var button = one.lib.dashlet.button.single("Remove Flow", one.f.flows.id.dashlet.remove, "btn-danger", "btn-mini");
-               var $button = one.lib.dashlet.button.button(button);
-               $button.click(function() {
-                   var $modal = one.f.flows.modal.dialog.initialize(id, node);
-                   $modal.modal();
-               });
-               // toggle button
-               var toggle;
-               if (flow['flow']['installInHw'] == 'true' && flow['flow']['status'] == 'Success') {
-                   toggle = one.lib.dashlet.button.single("Uninstall Flow", one.f.flows.id.dashlet.toggle, "btn-warning", "btn-mini");
-               } else {
-                   toggle = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.dashlet.toggle, "btn-success", "btn-mini");
-               }
-               var $toggle = one.lib.dashlet.button.button(toggle);
-               $toggle.click(function() {
-                   one.f.flows.modal.ajax.toggleflow(id, node, function(data) {
-                       if(data == "Success") {
-                           one.main.dashlet.right.bottom.empty();
-                           one.f.detail.dashlet(one.main.dashlet.right.bottom);
-                           one.main.dashlet.left.top.empty();
-                               one.f.flows.dashlet(one.main.dashlet.left.top, function() {
-                                  // checks are backwards due to stale registry
-                                  if(flow['flow']['installInHw'] == 'true') {
-                                      one.lib.alert('Uninstalled Flow');
-                                  } else {
-                                      one.lib.alert('Installed Flow');
-                                  }
-                                  one.f.flows.detail(id, node)
-                               });
-                       } else {
-                           one.lib.alert('Cannot toggle flow: '+data);
-                       }
-                   });
-               });
-
-               $detailDashlet.append($button).append($toggle);
+            // remove button
+            var button = one.lib.dashlet.button.single("Remove Flow", one.f.flows.id.dashlet.remove, "btn-danger", "btn-mini");
+            var $button = one.lib.dashlet.button.button(button);
+            $button.click(function() {
+                var $modal = one.f.flows.modal.dialog.initialize(id, node);
+                $modal.modal();
+            });
+            // toggle button
+            var toggle;
+            if (flow['flow']['installInHw'] == 'true' && flow['flow']['status'] == 'Success') {
+                toggle = one.lib.dashlet.button.single("Uninstall Flow", one.f.flows.id.dashlet.toggle, "btn-warning", "btn-mini");
+            } else {
+                toggle = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.dashlet.toggle, "btn-success", "btn-mini");
+            }
+            var $toggle = one.lib.dashlet.button.button(toggle);
+            $toggle.click(function() {
+                one.f.flows.modal.ajax.toggleflow(id, node, function(data) {
+                    if(data == "Success") {
+                        one.main.dashlet.right.bottom.empty();
+                        one.f.detail.dashlet(one.main.dashlet.right.bottom);
+                        one.main.dashlet.left.top.empty();
+                        one.f.flows.dashlet(one.main.dashlet.left.top, function() {
+                           // checks are backwards due to stale registry
+                           if(flow['flow']['installInHw'] == 'true') {
+                               one.lib.alert('Uninstalled Flow');
+                           } else {
+                               one.lib.alert('Installed Flow');
+                           }
+                           one.f.flows.detail(id, node)
+                        });
+                    } else {
+                        one.lib.alert('Cannot toggle flow: '+data);
+                    }
+                });
+            });
+
+            $detailDashlet.append($button).append($toggle);
         }
         // append details
         var body = one.f.detail.data.dashlet(flow);
         var $body = one.f.detail.body.dashlet(body);
         $detailDashlet.append($body);
-               var body = one.f.detail.data.description(flow);
-               var $body = one.f.detail.body.description(body);
-               $detailDashlet.append($body);
-               var body = one.f.detail.data.actions(flow);
-               var $body = one.f.detail.body.actions(body);
-               $detailDashlet.append($body);
+        var body = one.f.detail.data.description(flow);
+        var $body = one.f.detail.body.description(body);
+        $detailDashlet.append($body);
+        var body = one.f.detail.data.actions(flow);
+        var $body = one.f.detail.body.actions(body);
+        $detailDashlet.append($body);
     },
     modal : {
         dialog : {
@@ -492,8 +512,8 @@ one.f.flows = {
             result['ingressPort'] = $('#'+one.f.flows.id.modal.form.port, $modal).val();
             result['priority'] = $('#'+one.f.flows.id.modal.form.priority, $modal).val();
             result['hardTimeout'] = $('#'+one.f.flows.id.modal.form.hardTimeout, $modal).val();
-                       result['idleTimeout'] = $('#'+one.f.flows.id.modal.form.idleTimeout, $modal).val();
-                       result['cookie'] = $('#'+one.f.flows.id.modal.form.cookie, $modal).val();
+            result['idleTimeout'] = $('#'+one.f.flows.id.modal.form.idleTimeout, $modal).val();
+            result['cookie'] = $('#'+one.f.flows.id.modal.form.cookie, $modal).val();
             result['etherType'] = $('#'+one.f.flows.id.modal.form.etherType, $modal).val();
             result['vlanId'] = $('#'+one.f.flows.id.modal.form.vlanId, $modal).val();
             result['vlanPriority'] = $('#'+one.f.flows.id.modal.form.vlanPriority, $modal).val();
@@ -506,7 +526,7 @@ one.f.flows = {
             result['tpDst'] = $('#'+one.f.flows.id.modal.form.dstPort, $modal).val();
             result['protocol'] = $('#'+one.f.flows.id.modal.form.protocol, $modal).val();
 
-                       result['installInHw'] = install;
+            result['installInHw'] = install;
 
             var nodeId = $('#'+one.f.flows.id.modal.form.nodes, $modal).val();
 
@@ -517,31 +537,31 @@ one.f.flows = {
             var action = [];
             var $table = $('#'+one.f.flows.id.modal.action.table, $modal);
             $($table.find('tbody').find('tr')).each(function(index, value) {
-                               if (!$(this).find('td').hasClass('empty')) {
-                       action.push($(value).data('action'));
-                               }
+                if (!$(this).find('td').hasClass('empty')) {
+                    action.push($(value).data('action'));
+                }
             });
             result['actions'] = action;
 
             // frontend validation
-                       if (result['name'] == undefined) {
-                               alert('Need flow name');
-                               return;
-                       }
-                       if (nodeId == '') {
-                               alert('Select node');
-                               return;
-                       }
-                       if (action.length == 0) {
-                               alert('Please specify an action');
-                               return;
-                       }
-
-                       // package for ajax call
+            if (result['name'] == undefined) {
+                alert('Need flow name');
+                return;
+            }
+            if (nodeId == '') {
+                alert('Select node');
+                return;
+            }
+            if (action.length == 0) {
+                alert('Please specify an action');
+                return;
+            }
+
+            // package for ajax call
             var resource = {};
             resource['body'] = JSON.stringify(result);
             resource['action'] = 'add';
-                       resource['nodeId'] = nodeId;
+            resource['nodeId'] = nodeId;
 
             one.f.flows.modal.ajax.saveflow(resource, function(data) {
                 if (data == "Success") {
@@ -550,7 +570,7 @@ one.f.flows = {
                     one.main.dashlet.left.top.empty();
                     one.f.flows.dashlet(one.main.dashlet.left.top);
                 } else {
-                                       alert('Could not add flow: '+data);
+                    alert('Could not add flow: '+data);
                 }
             });
         },
@@ -570,18 +590,18 @@ one.f.flows = {
                 });
             },
             removeflow : function(id, node, callback) {
-               resource = {};
-               resource['action'] = 'remove';
+                resource = {};
+                resource['action'] = 'remove';
                 $.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
                     callback(data);
                 });
             },
             toggleflow : function(id, node, callback) {
-               resource = {};
-               resource['action'] = 'toggle';
-               $.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
-                       callback(data);
-               });
+                resource = {};
+                resource['action'] = 'toggle';
+                $.post(one.f.address.root+one.f.address.flows.flow+'/'+node+'/'+id, resource, function(data) {
+                    callback(data);
+                });
             }
         },
         data : {
@@ -595,184 +615,184 @@ one.f.flows = {
         },
         body : function(nodes, nodeports) {
             var $form = $(document.createElement('form'));
-                       var $fieldset = $(document.createElement('fieldset'));
-                       // flow description
-                       var $legend = one.lib.form.legend("Flow Description");
-                       $fieldset.append($legend);
-                       // name
-                       var $label = one.lib.form.label("Name");
-                       var $input = one.lib.form.input("Flow Name");
-                       $input.attr('id', one.f.flows.id.modal.form.name);
-                       $fieldset.append($label).append($input);
-                       // node
-                       var $label = one.lib.form.label("Node");
-                       var $select = one.lib.form.select.create(nodes);
-                       one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
-                       $select.val($select.find("option:first").val());
-                       $select.attr('id', one.f.flows.id.modal.form.nodes);
-
-                       // bind onchange
-                       $select.change(function() {
-                           // retrieve port value
-                           var node = $(this).find('option:selected').attr('value');
-                           var $ports = $('#'+one.f.flows.id.modal.form.port);
-                               if (node == '') {
-                                       one.lib.form.select.inject($ports, {});
-                                       return;
-                               }
-                           one.f.flows.registry['currentNode'] = node;
-                           var ports = nodeports[node]['ports'];
-                           one.lib.form.select.inject($ports, ports);
-                           one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' });
-                           $ports.val($ports.find("option:first").val());
-                       });
+            var $fieldset = $(document.createElement('fieldset'));
+            // flow description
+            var $legend = one.lib.form.legend("Flow Description");
+            $fieldset.append($legend);
+            // name
+            var $label = one.lib.form.label("Name");
+            var $input = one.lib.form.input("Flow Name");
+            $input.attr('id', one.f.flows.id.modal.form.name);
+            $fieldset.append($label).append($input);
+            // node
+            var $label = one.lib.form.label("Node");
+            var $select = one.lib.form.select.create(nodes);
+            one.lib.form.select.prepend($select, { '' : 'Please Select a Node' });
+            $select.val($select.find("option:first").val());
+            $select.attr('id', one.f.flows.id.modal.form.nodes);
+
+            // bind onchange
+            $select.change(function() {
+                // retrieve port value
+                var node = $(this).find('option:selected').attr('value');
+                var $ports = $('#'+one.f.flows.id.modal.form.port);
+                if (node == '') {
+                    one.lib.form.select.inject($ports, {});
+                    return;
+                }
+                one.f.flows.registry['currentNode'] = node;
+                var ports = nodeports[node]['ports'];
+                one.lib.form.select.inject($ports, ports);
+                one.lib.form.select.prepend($ports, { '' : 'Please Select a Port' });
+                $ports.val($ports.find("option:first").val());
+            });
 
             $fieldset.append($label).append($select);
-                       // input port
-                       var $label = one.lib.form.label("Input Port");
-                       var $select = one.lib.form.select.create();
-                       $select.attr('id', one.f.flows.id.modal.form.port);
-                       $fieldset.append($label).append($select);
-                       // priority
-                       var $label = one.lib.form.label("Priority");
-                       var $input = one.lib.form.input("Priority");
-                       $input.attr('id', one.f.flows.id.modal.form.priority);
-                       $input.val('500');
-                       $fieldset.append($label).append($input);
-                       // hardTimeout
-                       var $label = one.lib.form.label("Hard Timeout");
-                       var $input = one.lib.form.input("Hard Timeout");
-                       $input.attr('id', one.f.flows.id.modal.form.hardTimeout);
-                       $fieldset.append($label).append($input);
-                       // idleTimeout
-                       var $label = one.lib.form.label("Idle Timeout");
-                       var $input = one.lib.form.input("Idle Timeout");
-                       $input.attr('id', one.f.flows.id.modal.form.idleTimeout);
-                       $fieldset.append($label).append($input);
-                       // cookie
-                       var $label = one.lib.form.label("Cookie");
-                       var $input = one.lib.form.input("Cookie");
-                       $input.attr('id', one.f.flows.id.modal.form.cookie);
-                       $fieldset.append($label).append($input);
-                       // layer 2
-                       var $legend = one.lib.form.legend("Layer 2");
-                       $fieldset.append($legend);
-                       // etherType
-                       var $label = one.lib.form.label("Ethernet Type");
-                       var $input = one.lib.form.input("Ethernet Type");
-                       $input.attr('id', one.f.flows.id.modal.form.etherType);
-                       $input.val('0x800');
-                       $fieldset.append($label).append($input);
-                       // vlanId
-                       var $label = one.lib.form.label("VLAN Identification Number");
-                       var $input = one.lib.form.input("VLAN Identification Number");
-                       $input.attr('id', one.f.flows.id.modal.form.vlanId);
-                       var $help = one.lib.form.help("Range: 0 - 4095");
-                       $fieldset.append($label).append($input).append($help);
-                       // vlanPriority
-                       var $label = one.lib.form.label("VLAN Priority");
-                       var $input = one.lib.form.input("VLAN Priority");
-                       $input.attr('id', one.f.flows.id.modal.form.vlanPriority);
-                       var $help = one.lib.form.help("Range: 0 - 7");
-                       $fieldset.append($label).append($input).append($help);
-                       // srcMac
-                       var $label = one.lib.form.label("Source MAC Address");
-                       var $input = one.lib.form.input("Source MAC Address");
-                       $input.attr('id', one.f.flows.id.modal.form.srcMac);
-                       var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
-                       $fieldset.append($label).append($input).append($help);
-                       // dstMac
-                       var $label = one.lib.form.label("Destination MAC Address");
-                       var $input = one.lib.form.input("Destination MAC Address");
-                       $input.attr('id', one.f.flows.id.modal.form.dstMac);
-                       var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
-                       $fieldset.append($label).append($input).append($help);
-                       // layer 3
-                       var $legend = one.lib.form.legend("Layer 3");
-                       $fieldset.append($legend);
-                       // srcIp
-                       var $label = one.lib.form.label("Source IP Address");
-                       var $input = one.lib.form.input("Source IP Address");
-                       $input.attr('id', one.f.flows.id.modal.form.srcIp);
-                       var $help = one.lib.form.help("Example: 127.0.0.1");
-                       $fieldset.append($label).append($input).append($help);
-                       // dstIp
-                       var $label = one.lib.form.label("Destination IP Address");
-                       var $input = one.lib.form.input("Destination IP Address");
-                       $input.attr('id', one.f.flows.id.modal.form.dstIp);
-                       var $help = one.lib.form.help("Example: 127.0.0.1");
-                       $fieldset.append($label).append($input).append($help);
-                       // tosBits
-                       var $label = one.lib.form.label("TOS Bits");
-                       var $input = one.lib.form.input("TOS Bits");
-                       $input.attr('id', one.f.flows.id.modal.form.tosBits);
-                       var $help = one.lib.form.help("Range: 0 - 63");
-                       $fieldset.append($label).append($input).append($help);
-                       // layer 4
-                       var $legend = one.lib.form.legend("Layer 4");
-                       $fieldset.append($legend);
-                       // srcPort
-                       var $label = one.lib.form.label("Source Port");
-                       var $input = one.lib.form.input("Source Port");
-                       $input.attr('id', one.f.flows.id.modal.form.srcPort);
-                       var $help = one.lib.form.help("Range: 0 - 65535");
-                       $fieldset.append($label).append($input).append($help);
-                       // dstPort
-                       var $label = one.lib.form.label("Destination Port");
-                       var $input = one.lib.form.input("Destination Port");
-                       $input.attr('id', one.f.flows.id.modal.form.dstPort);
-                       var $help = one.lib.form.help("Range: 0 - 65535");
-                       $fieldset.append($label).append($input).append($help);
-                       // protocol
-                       var $label = one.lib.form.label("Protocol");
-                       var $input = one.lib.form.input("Protocol");
-                       $input.attr('id', one.f.flows.id.modal.form.protocol);
-                       $fieldset.append($label).append($input);
-                       // actions
-                       var $legend = one.lib.form.label("Actions");
-                       $fieldset.append($legend);
-                       // actions table
-                       var tableAttributes = ["table-striped", "table-bordered", "table-condensed", "table-hover", "table-cursor"];
-                       var $table = one.lib.dashlet.table.table(tableAttributes);
-                       $table.attr('id', one.f.flows.id.modal.action.table);
-                       var tableHeaders = ["Action", "Data", "Type"];
-                   var $thead = one.lib.dashlet.table.header(tableHeaders);
-                       var $tbody = one.lib.dashlet.table.body("", tableHeaders);
-                       $table.append($thead).append($tbody);
-                       // actions
-                       var actions = {
-                           "" : "Please Select an Action",
-                           "drop" : "Drop",
-                           "loopback" : "Loopback",
-                           "flood" : "Flood",
-                           "softwarePath" : "Software Path",
-                           "hardwarePath" : "Hardware Path",
-                           "controller" : "Controller",
-                           "addOutputPorts" : "Add Output Ports",
-                           "setVlanId" : "Set VLAN ID",
-                           "setVlanPriority" : "Set VLAN Priority",
-                           "stripVlanHeader" : "Strip VLAN Header",
-                           "modifyDatalayerSourceAddress" : "Modify Datalayer Source Address",
-                           "modifyDatalayerDestinationAddress" : "Modify Datalayer Destination Address",
-                           "modifyNetworkSourceAddress" : "Modify Network Source Address",
-                           "modifyNetworkDestinationAddress" :"Modify Network Destination Address",
-                           "modifyTosBits" : "Modify TOS Bits",
-                           "modifyTransportSourcePort" : "Modify Transport Source Port",
-                           "modifyTransportDestinationPort" : "Modify Transport Destination Port"
-                       };
+            // input port
+            var $label = one.lib.form.label("Input Port");
+            var $select = one.lib.form.select.create();
+            $select.attr('id', one.f.flows.id.modal.form.port);
+            $fieldset.append($label).append($select);
+            // priority
+            var $label = one.lib.form.label("Priority");
+            var $input = one.lib.form.input("Priority");
+            $input.attr('id', one.f.flows.id.modal.form.priority);
+            $input.val('500');
+            $fieldset.append($label).append($input);
+            // hardTimeout
+            var $label = one.lib.form.label("Hard Timeout");
+            var $input = one.lib.form.input("Hard Timeout");
+            $input.attr('id', one.f.flows.id.modal.form.hardTimeout);
+            $fieldset.append($label).append($input);
+            // idleTimeout
+            var $label = one.lib.form.label("Idle Timeout");
+            var $input = one.lib.form.input("Idle Timeout");
+            $input.attr('id', one.f.flows.id.modal.form.idleTimeout);
+            $fieldset.append($label).append($input);
+            // cookie
+            var $label = one.lib.form.label("Cookie");
+            var $input = one.lib.form.input("Cookie");
+            $input.attr('id', one.f.flows.id.modal.form.cookie);
+            $fieldset.append($label).append($input);
+            // layer 2
+            var $legend = one.lib.form.legend("Layer 2");
+            $fieldset.append($legend);
+            // etherType
+            var $label = one.lib.form.label("Ethernet Type");
+            var $input = one.lib.form.input("Ethernet Type");
+            $input.attr('id', one.f.flows.id.modal.form.etherType);
+            $input.val('0x800');
+            $fieldset.append($label).append($input);
+            // vlanId
+            var $label = one.lib.form.label("VLAN Identification Number");
+            var $input = one.lib.form.input("VLAN Identification Number");
+            $input.attr('id', one.f.flows.id.modal.form.vlanId);
+            var $help = one.lib.form.help("Range: 0 - 4095");
+            $fieldset.append($label).append($input).append($help);
+            // vlanPriority
+            var $label = one.lib.form.label("VLAN Priority");
+            var $input = one.lib.form.input("VLAN Priority");
+            $input.attr('id', one.f.flows.id.modal.form.vlanPriority);
+            var $help = one.lib.form.help("Range: 0 - 7");
+            $fieldset.append($label).append($input).append($help);
+            // srcMac
+            var $label = one.lib.form.label("Source MAC Address");
+            var $input = one.lib.form.input("Source MAC Address");
+            $input.attr('id', one.f.flows.id.modal.form.srcMac);
+            var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
+            $fieldset.append($label).append($input).append($help);
+            // dstMac
+            var $label = one.lib.form.label("Destination MAC Address");
+            var $input = one.lib.form.input("Destination MAC Address");
+            $input.attr('id', one.f.flows.id.modal.form.dstMac);
+            var $help = one.lib.form.help("Example: 00:11:22:aa:bb:cc");
+            $fieldset.append($label).append($input).append($help);
+            // layer 3
+            var $legend = one.lib.form.legend("Layer 3");
+            $fieldset.append($legend);
+            // srcIp
+            var $label = one.lib.form.label("Source IP Address");
+            var $input = one.lib.form.input("Source IP Address");
+            $input.attr('id', one.f.flows.id.modal.form.srcIp);
+            var $help = one.lib.form.help("Example: 127.0.0.1");
+            $fieldset.append($label).append($input).append($help);
+            // dstIp
+            var $label = one.lib.form.label("Destination IP Address");
+            var $input = one.lib.form.input("Destination IP Address");
+            $input.attr('id', one.f.flows.id.modal.form.dstIp);
+            var $help = one.lib.form.help("Example: 127.0.0.1");
+            $fieldset.append($label).append($input).append($help);
+            // tosBits
+            var $label = one.lib.form.label("TOS Bits");
+            var $input = one.lib.form.input("TOS Bits");
+            $input.attr('id', one.f.flows.id.modal.form.tosBits);
+            var $help = one.lib.form.help("Range: 0 - 63");
+            $fieldset.append($label).append($input).append($help);
+            // layer 4
+            var $legend = one.lib.form.legend("Layer 4");
+            $fieldset.append($legend);
+            // srcPort
+            var $label = one.lib.form.label("Source Port");
+            var $input = one.lib.form.input("Source Port");
+            $input.attr('id', one.f.flows.id.modal.form.srcPort);
+            var $help = one.lib.form.help("Range: 0 - 65535");
+            $fieldset.append($label).append($input).append($help);
+            // dstPort
+            var $label = one.lib.form.label("Destination Port");
+            var $input = one.lib.form.input("Destination Port");
+            $input.attr('id', one.f.flows.id.modal.form.dstPort);
+            var $help = one.lib.form.help("Range: 0 - 65535");
+            $fieldset.append($label).append($input).append($help);
+            // protocol
+            var $label = one.lib.form.label("Protocol");
+            var $input = one.lib.form.input("Protocol");
+            $input.attr('id', one.f.flows.id.modal.form.protocol);
+            $fieldset.append($label).append($input);
+            // actions
+            var $legend = one.lib.form.label("Actions");
+            $fieldset.append($legend);
+            // actions table
+            var tableAttributes = ["table-striped", "table-bordered", "table-condensed", "table-hover", "table-cursor"];
+            var $table = one.lib.dashlet.table.table(tableAttributes);
+            $table.attr('id', one.f.flows.id.modal.action.table);
+            var tableHeaders = ["Action", "Data", "Type"];
+            var $thead = one.lib.dashlet.table.header(tableHeaders);
+            var $tbody = one.lib.dashlet.table.body("", tableHeaders);
+            $table.append($thead).append($tbody);
+            // actions
+            var actions = {
+                "" : "Please Select an Action",
+                "drop" : "Drop",
+                "loopback" : "Loopback",
+                "flood" : "Flood",
+                "softwarePath" : "Software Path",
+                "hardwarePath" : "Hardware Path",
+                "controller" : "Controller",
+                "addOutputPorts" : "Add Output Ports",
+                "setVlanId" : "Set VLAN ID",
+                "setVlanPriority" : "Set VLAN Priority",
+                "stripVlanHeader" : "Strip VLAN Header",
+                "modifyDatalayerSourceAddress" : "Modify Datalayer Source Address",
+                "modifyDatalayerDestinationAddress" : "Modify Datalayer Destination Address",
+                "modifyNetworkSourceAddress" : "Modify Network Source Address",
+                "modifyNetworkDestinationAddress" :"Modify Network Destination Address",
+                "modifyTosBits" : "Modify TOS Bits",
+                "modifyTransportSourcePort" : "Modify Transport Source Port",
+                "modifyTransportDestinationPort" : "Modify Transport Destination Port"
+            };
             var $select = one.lib.form.select.create(actions);
             // when selecting an action
             $select.change(function() {
                 var action = $(this).find('option:selected');
                 one.f.flows.modal.action.parse(action.attr('value'));
-                               $select[0].selectedIndex = 0;
+                $select[0].selectedIndex = 0;
             });
 
-                       $fieldset.append($select).append($table);
+            $fieldset.append($select).append($table);
 
-                       // return
-                       $form.append($fieldset);
-                       return $form;
+            // return
+            $form.append($fieldset);
+            return $form;
         },
         action : {
             parse : function(option) {
@@ -991,9 +1011,9 @@ one.f.flows = {
                     var $tr = one.f.flows.modal.action.table.add("Add Output Ports", ports);
                     $tr.attr('id', 'addOutputPorts');
                     $tr.data('action', 'OUTPUT='+pid);
-                                       $tr.click(function() {
-                                               one.f.flows.modal.action.add.modal.initialize(this);
-                                       });
+                    $tr.click(function() {
+                        one.f.flows.modal.action.add.modal.initialize(this);
+                    });
                     one.f.flows.modal.action.table.append($tr);
                     $modal.modal('hide');
                 },
@@ -1001,9 +1021,9 @@ one.f.flows = {
                     var $tr = one.f.flows.modal.action.table.add(name);
                     $tr.attr('id', action);
                     $tr.data('action', action);
-                                       $tr.click(function() {
-                                               one.f.flows.modal.action.add.modal.initialize(this);
-                                       });
+                    $tr.click(function() {
+                        one.f.flows.modal.action.add.modal.initialize(this);
+                    });
                     one.f.flows.modal.action.table.append($tr);
                 },
                 set : function(name, id, action, $modal) {
@@ -1012,64 +1032,64 @@ one.f.flows = {
                     var $tr = one.f.flows.modal.action.table.add(name, value);
                     $tr.attr('id', action);
                     $tr.data('action', action+'='+value);
-                                       $tr.click(function() {
-                                               one.f.flows.modal.action.add.modal.initialize(this);
-                                       });
+                    $tr.click(function() {
+                        one.f.flows.modal.action.add.modal.initialize(this);
+                    });
                     one.f.flows.modal.action.table.append($tr);
                     $modal.modal('hide');
                 },
-                               remove : function(that) {
-                                       $(that).remove();
-                                       var $table = $('#'+one.f.flows.id.modal.action.table);
-                                       if ($table.find('tbody').find('tr').size() == 0) {
-                                               var $tr = $(document.createElement('tr'));
-                                               var $td = $(document.createElement('td'));
-                                               $td.attr('colspan', '3');
-                                               $tr.addClass('empty');
-                                               $td.text('No data available');
-                                               $tr.append($td);
-                                               $table.find('tbody').append($tr);
-                                       }
-                               },
-                               modal : {
-                                       initialize : function(that) {
-                                               var h3 = "Remove Action";
-                                               var footer = one.f.flows.modal.action.add.modal.footer();
-                                               var $body = one.f.flows.modal.action.add.modal.body();
-                                               var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal.modal, h3, $body, footer);
-
-                                               // bind cancel button
-                                               $('#'+one.f.flows.id.modal.action.modal.cancel, $modal).click(function() {
-                                                       $modal.modal('hide');
-                                               });
-
-                                               // bind remove button
-                                               $('#'+one.f.flows.id.modal.action.modal.remove, $modal).click(function() {
-                                                       one.f.flows.modal.action.add.remove(that);
-                                                       $modal.modal('hide');
-                                               });
-
-                                               $modal.modal();
-                                       },
-                                       body : function() {
-                                               var $p = $(document.createElement('p'));
-                                               $p.append("Remove this action?");
-                                               return $p;
-                                       },
-                                       footer : function() {
-                                               var footer = [];
-
-                                               var removeButton = one.lib.dashlet.button.single("Remove Action", one.f.flows.id.modal.action.modal.remove, "btn-danger", "");
-                                               var $removeButton = one.lib.dashlet.button.button(removeButton);
-                                               footer.push($removeButton);
-
-                                               var cancelButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.action.modal.cancel, "", "");
-                                               var $cancelButton = one.lib.dashlet.button.button(cancelButton);
-                                               footer.push($cancelButton);
-
-                                               return footer;
-                                       }
-                               }
+                remove : function(that) {
+                    $(that).remove();
+                    var $table = $('#'+one.f.flows.id.modal.action.table);
+                    if ($table.find('tbody').find('tr').size() == 0) {
+                        var $tr = $(document.createElement('tr'));
+                        var $td = $(document.createElement('td'));
+                        $td.attr('colspan', '3');
+                        $tr.addClass('empty');
+                        $td.text('No data available');
+                        $tr.append($td);
+                        $table.find('tbody').append($tr);
+                    }
+                },
+                modal : {
+                    initialize : function(that) {
+                        var h3 = "Remove Action";
+                        var footer = one.f.flows.modal.action.add.modal.footer();
+                        var $body = one.f.flows.modal.action.add.modal.body();
+                        var $modal = one.lib.modal.spawn(one.f.flows.id.modal.action.modal.modal, h3, $body, footer);
+
+                        // bind cancel button
+                        $('#'+one.f.flows.id.modal.action.modal.cancel, $modal).click(function() {
+                            $modal.modal('hide');
+                        });
+
+                        // bind remove button
+                        $('#'+one.f.flows.id.modal.action.modal.remove, $modal).click(function() {
+                            one.f.flows.modal.action.add.remove(that);
+                            $modal.modal('hide');
+                        });
+
+                        $modal.modal();
+                    },
+                    body : function() {
+                        var $p = $(document.createElement('p'));
+                        $p.append("Remove this action?");
+                        return $p;
+                    },
+                    footer : function() {
+                        var footer = [];
+
+                        var removeButton = one.lib.dashlet.button.single("Remove Action", one.f.flows.id.modal.action.modal.remove, "btn-danger", "");
+                        var $removeButton = one.lib.dashlet.button.button(removeButton);
+                        footer.push($removeButton);
+
+                        var cancelButton = one.lib.dashlet.button.single("Cancel", one.f.flows.id.modal.action.modal.cancel, "", "");
+                        var $cancelButton = one.lib.dashlet.button.button(cancelButton);
+                        footer.push($cancelButton);
+
+                        return footer;
+                    }
+                }
             },
             table : {
                 add : function(action, data, type) {
@@ -1143,9 +1163,9 @@ one.f.flows = {
         footer : function() {
             var footer = [];
 
-                       var installButton = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.modal.install, "btn-success", "");
-                       var $installButton = one.lib.dashlet.button.button(installButton);
-                       footer.push($installButton);
+            var installButton = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.modal.install, "btn-success", "");
+            var $installButton = one.lib.dashlet.button.button(installButton);
+            footer.push($installButton);
 
             var addButton = one.lib.dashlet.button.single("Save Flow", one.f.flows.id.modal.add, "btn-primary", "");
             var $addButton = one.lib.dashlet.button.button(addButton);
@@ -1163,13 +1183,38 @@ one.f.flows = {
             $.getJSON(one.f.address.root+one.f.address.flows.main, function(data) {
                 one.f.flows.registry['flows'] = data.flows;
                 one.f.flows.registry['privilege'] = data.privilege;
-                var body = one.f.flows.data.dashlet(data.flows);
-                var $body = one.f.flows.body.dashlet(body, callback);
-                callback($body);
+                callback(data);
             });
         }
     },
     data : {
+        flowsDataGrid: function(data) {
+            var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'name',
+                            label: 'Flow Name',
+                            sortable: true
+                        },
+                        {
+                            property: 'node',
+                            label: 'Node',
+                            sortable: true
+                        }
+                    ],
+                    data: data.flows,
+                    formatter: function(items) {
+                        $.each(items, function(index, item) {
+                            item["name"] = '<span data-installInHw=' + item["flow"]["installInHw"] + 
+                                ' data-flowstatus=' + item["flow"]["status"] + 
+                                ' data-nodeId=' + item["nodeId"] + '>' + item["name"] + '</span>';
+                        });
+
+                    },
+                    delay: 0
+                });
+            return source;
+        },
         dashlet : function(data) {
             var body = [];
             $(data).each(function(index, value) {
@@ -1178,11 +1223,11 @@ one.f.flows = {
                 entry.push(value['name']);
                 entry.push(value['node']);
                 if (value['flow']['installInHw'] == 'true' && value['flow']['status'] == 'Success')
-                       tr['type'] = ['success'];
+                    tr['type'] = ['success'];
                 else if (value['flow']['installInHw'] == 'false' && value['flow']['status'] == 'Success')
-                       tr['type'] = ['warning'];
+                    tr['type'] = ['warning'];
                 else 
-                       tr['type'] = ['warning'];
+                    tr['type'] = ['warning'];
                 tr['entry'] = entry;
                 tr['id'] = value['nodeId'];
 
index ba2075ddb6a50c198e4d3fbb4d38369391c4fa13..524cb62b3a2175d24596f4b5727a5d7a57310005 100644 (file)
@@ -30,6 +30,9 @@ import com.google.gson.Gson;
 @Controller
 @RequestMapping("/admin")
 public class DaylightWebAdmin {
+
+
+
     @RequestMapping("/users")
     @ResponseBody
     public List<UserConfig> getUsers() {
@@ -69,7 +72,11 @@ public class DaylightWebAdmin {
 
         Status result = (action.equals("add")) ? userManager
                 .addLocalUser(config) : userManager.removeLocalUser(config);
-
+        if(result.getCode().equals(StatusCode.SUCCESS)) {
+            String userAction=(action.equals("add")) ? "added":"removed";
+            DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser());
+            return "Success";
+        }
         return result.getDescription();
     }
 
@@ -93,7 +100,12 @@ public class DaylightWebAdmin {
             return "Operation not permitted";
         }
 
-        return userManager.removeLocalUser(userName).getDescription();
+        Status result = userManager.removeLocalUser(userName);
+        if(result.getCode().equals(StatusCode.SUCCESS)) {
+            DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", userName);
+            return "Success";
+        }
+        return result.getDescription();
     }
 
     @RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST)
@@ -115,7 +127,9 @@ public class DaylightWebAdmin {
         }
 
         Status status = userManager.changeLocalUserPassword(username, currentPassword, newPassword);
-
+        if(status.isSuccess()){
+            DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "changed password for", username);
+        }
         return status;
     }
 
index ab2abe9c9ed136e32d15d5c3f992dde5cd4d9b8e..3add0e6a40b22d0745421d7f0d4db46a82babbfa 100644 (file)
@@ -5,9 +5,14 @@ import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.usermanager.IUserManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class DaylightWebUtil {
 
+    private static final String AUDIT = "audit";
+    private static final Logger logger = LoggerFactory.getLogger(AUDIT);
+
     /**
      * Returns the access privilege the user has on the specified container
      *
@@ -52,4 +57,21 @@ public class DaylightWebUtil {
 
         return Privilege.NONE;
     }
+
+    public static void auditlog(String moduleName, String user, String action, String resource,
+            String containerName) {
+        String auditMsg = "";
+        String mode = "WEB";
+        if (containerName != null) {
+            auditMsg = "Mode: " + mode + " User " + user + " "  + action + " " + moduleName + " " + resource + " in container "
+                    + containerName;
+        } else {
+            auditMsg = "Mode: " + mode + " User " + user + " "  + action + " " + moduleName + " " + resource;
+        }
+        logger.info(auditMsg);
+    }
+
+    public static void auditlog(String moduleName, String user, String action, String resource) {
+        auditlog(moduleName, user, action, resource, null);
+    }
 }
\ No newline at end of file
index a532560bcde4b3166cf42c7f7bc8e62fc83ef068..c7c3ef16c3fb037c55e0405ff0b46e5ef09c08fb 100644 (file)
@@ -16,6 +16,8 @@
 
 <!-- Bootstrap CSS - 1 -->
 <link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
+<link rel="stylesheet" type="text/css" href="/css/fuelux.min.css">
+<link rel="stylesheet" type="text/css" href="/css/opendaylight.css">
 
 <!-- Core CSS - 2 -->
 <link rel="stylesheet/less" type="text/css" href="/css/one.less">
@@ -38,7 +40,9 @@
 <script src="/js/jquery-1.9.1.min.js"></script>
 
 <!-- Bootstrap JS - 2 -->
-<script src="/js/bootstrap.min.js"></script>
+<script src="/js/underscore-min.js"></script>
+<script src="/js/fuelux/loader.min.js"></script>
+<script src="/js/datasource.js"></script>
 
 <!-- LESS - 3 -->
 <script type="text/javascript">
diff --git a/opendaylight/web/root/src/main/resources/css/fuelux-responsive.min.css b/opendaylight/web/root/src/main/resources/css/fuelux-responsive.min.css
new file mode 100755 (executable)
index 0000000..1dbe323
--- /dev/null
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap Responsive v2.3.2
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.fuelux .clearfix{*zoom:1}.fuelux .clearfix:before,.fuelux .clearfix:after{display:table;line-height:0;content:""}.fuelux .clearfix:after{clear:both}.fuelux .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.fuelux .input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.fuelux .hidden{display:none;visibility:hidden}.fuelux .visible-phone{display:none!important}.fuelux .visible-tablet{display:none!important}.fuelux .hidden-desktop{display:none!important}.fuelux .visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.fuelux .hidden-desktop{display:inherit!important}.fuelux .visible-desktop{display:none!important}.fuelux .visible-tablet{display:inherit!important}.fuelux .hidden-tablet{display:none!important}}@media(max-width:767px){.fuelux .hidden-desktop{display:inherit!important}.fuelux .visible-desktop{display:none!important}.fuelux .visible-phone{display:inherit!important}.fuelux .hidden-phone{display:none!important}}.fuelux .visible-print{display:none!important}@media print{.fuelux .visible-print{display:inherit!important}.fuelux .hidden-print{display:none!important}}@media(min-width:1200px){.fuelux .row{margin-left:-30px;*zoom:1}.fuelux .row:before,.fuelux .row:after{display:table;line-height:0;content:""}.fuelux .row:after{clear:both}.fuelux [class*="span"]{float:left;min-height:1px;margin-left:30px}.fuelux .container,.fuelux .navbar-static-top .container,.fuelux .navbar-fixed-top .container,.fuelux .navbar-fixed-bottom .container{width:1170px}.fuelux .span12{width:1170px}.fuelux .span11{width:1070px}.fuelux .span10{width:970px}.fuelux .span9{width:870px}.fuelux .span8{width:770px}.fuelux .span7{width:670px}.fuelux .span6{width:570px}.fuelux .span5{width:470px}.fuelux .span4{width:370px}.fuelux .span3{width:270px}.fuelux .span2{width:170px}.fuelux .span1{width:70px}.fuelux .offset12{margin-left:1230px}.fuelux .offset11{margin-left:1130px}.fuelux .offset10{margin-left:1030px}.fuelux .offset9{margin-left:930px}.fuelux .offset8{margin-left:830px}.fuelux .offset7{margin-left:730px}.fuelux .offset6{margin-left:630px}.fuelux .offset5{margin-left:530px}.fuelux .offset4{margin-left:430px}.fuelux .offset3{margin-left:330px}.fuelux .offset2{margin-left:230px}.fuelux .offset1{margin-left:130px}.fuelux .row-fluid{width:100%;*zoom:1}.fuelux .row-fluid:before,.fuelux .row-fluid:after{display:table;line-height:0;content:""}.fuelux .row-fluid:after{clear:both}.fuelux .row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fuelux .row-fluid [class*="span"]:first-child{margin-left:0}.fuelux .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.fuelux .row-fluid .span12{width:100%;*width:99.94680851063829%}.fuelux .row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.fuelux .row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.fuelux .row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.fuelux .row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.fuelux .row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.fuelux .row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.fuelux .row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.fuelux .row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.fuelux .row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.fuelux .row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.fuelux .row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.fuelux .row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.fuelux .row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.fuelux .row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.fuelux .row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.fuelux .row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.fuelux .row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.fuelux .row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.fuelux .row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.fuelux .row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.fuelux .row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.fuelux .row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.fuelux .row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.fuelux .row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.fuelux .row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.fuelux .row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.fuelux .row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.fuelux .row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.fuelux .row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.fuelux .row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.fuelux .row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.fuelux .row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.fuelux .row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.fuelux .row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.fuelux .row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}.fuelux input,.fuelux textarea,.fuelux .uneditable-input{margin-left:0}.fuelux .controls-row [class*="span"]+[class*="span"]{margin-left:30px}.fuelux input.span12,textarea.span12,.uneditable-input.span12{width:1156px}.fuelux input.span11,textarea.span11,.uneditable-input.span11{width:1056px}.fuelux input.span10,textarea.span10,.uneditable-input.span10{width:956px}.fuelux input.span9,textarea.span9,.uneditable-input.span9{width:856px}.fuelux input.span8,textarea.span8,.uneditable-input.span8{width:756px}.fuelux input.span7,textarea.span7,.uneditable-input.span7{width:656px}.fuelux input.span6,textarea.span6,.uneditable-input.span6{width:556px}.fuelux input.span5,textarea.span5,.uneditable-input.span5{width:456px}.fuelux input.span4,textarea.span4,.uneditable-input.span4{width:356px}.fuelux input.span3,textarea.span3,.uneditable-input.span3{width:256px}.fuelux input.span2,textarea.span2,.uneditable-input.span2{width:156px}.fuelux input.span1,textarea.span1,.uneditable-input.span1{width:56px}.fuelux .thumbnails{margin-left:-30px}.fuelux .thumbnails>li{margin-left:30px}.fuelux .row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.fuelux .row{margin-left:-20px;*zoom:1}.fuelux .row:before,.fuelux .row:after{display:table;line-height:0;content:""}.fuelux .row:after{clear:both}.fuelux [class*="span"]{float:left;min-height:1px;margin-left:20px}.fuelux .container,.fuelux .navbar-static-top .container,.fuelux .navbar-fixed-top .container,.fuelux .navbar-fixed-bottom .container{width:724px}.fuelux .span12{width:724px}.fuelux .span11{width:662px}.fuelux .span10{width:600px}.fuelux .span9{width:538px}.fuelux .span8{width:476px}.fuelux .span7{width:414px}.fuelux .span6{width:352px}.fuelux .span5{width:290px}.fuelux .span4{width:228px}.fuelux .span3{width:166px}.fuelux .span2{width:104px}.fuelux .span1{width:42px}.fuelux .offset12{margin-left:764px}.fuelux .offset11{margin-left:702px}.fuelux .offset10{margin-left:640px}.fuelux .offset9{margin-left:578px}.fuelux .offset8{margin-left:516px}.fuelux .offset7{margin-left:454px}.fuelux .offset6{margin-left:392px}.fuelux .offset5{margin-left:330px}.fuelux .offset4{margin-left:268px}.fuelux .offset3{margin-left:206px}.fuelux .offset2{margin-left:144px}.fuelux .offset1{margin-left:82px}.fuelux .row-fluid{width:100%;*zoom:1}.fuelux .row-fluid:before,.fuelux .row-fluid:after{display:table;line-height:0;content:""}.fuelux .row-fluid:after{clear:both}.fuelux .row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fuelux .row-fluid [class*="span"]:first-child{margin-left:0}.fuelux .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.fuelux .row-fluid .span12{width:100%;*width:99.94680851063829%}.fuelux .row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.fuelux .row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.fuelux .row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.fuelux .row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.fuelux .row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.fuelux .row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.fuelux .row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.fuelux .row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.fuelux .row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.fuelux .row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.fuelux .row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.fuelux .row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.fuelux .row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.fuelux .row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.fuelux .row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.fuelux .row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.fuelux .row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.fuelux .row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.fuelux .row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.fuelux .row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.fuelux .row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.fuelux .row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.fuelux .row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.fuelux .row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.fuelux .row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.fuelux .row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.fuelux .row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.fuelux .row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.fuelux .row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.fuelux .row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.fuelux .row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.fuelux .row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.fuelux .row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.fuelux .row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.fuelux .row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}.fuelux input,.fuelux textarea,.fuelux .uneditable-input{margin-left:0}.fuelux .controls-row [class*="span"]+[class*="span"]{margin-left:20px}.fuelux input.span12,textarea.span12,.uneditable-input.span12{width:710px}.fuelux input.span11,textarea.span11,.uneditable-input.span11{width:648px}.fuelux input.span10,textarea.span10,.uneditable-input.span10{width:586px}.fuelux input.span9,textarea.span9,.uneditable-input.span9{width:524px}.fuelux input.span8,textarea.span8,.uneditable-input.span8{width:462px}.fuelux input.span7,textarea.span7,.uneditable-input.span7{width:400px}.fuelux input.span6,textarea.span6,.uneditable-input.span6{width:338px}.fuelux input.span5,textarea.span5,.uneditable-input.span5{width:276px}.fuelux input.span4,textarea.span4,.uneditable-input.span4{width:214px}.fuelux input.span3,textarea.span3,.uneditable-input.span3{width:152px}.fuelux input.span2,textarea.span2,.uneditable-input.span2{width:90px}.fuelux input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){.fuelux body{padding-right:20px;padding-left:20px}.fuelux .navbar-fixed-top,.fuelux .navbar-fixed-bottom,.fuelux .navbar-static-top{margin-right:-20px;margin-left:-20px}.fuelux .container-fluid{padding:0}.fuelux .dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.fuelux .dl-horizontal dd{margin-left:0}.fuelux .container{width:auto}.fuelux .row-fluid{width:100%}.fuelux .row,.fuelux .thumbnails{margin-left:0}.fuelux .thumbnails>li{float:none;margin-left:0}.fuelux [class*="span"],.fuelux .uneditable-input[class*="span"],.fuelux .row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fuelux .span12,.fuelux .row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fuelux .row-fluid [class*="offset"]:first-child{margin-left:0}.fuelux .input-large,.fuelux .input-xlarge,.fuelux .input-xxlarge,.fuelux input[class*="span"],.fuelux select[class*="span"],.fuelux textarea[class*="span"],.fuelux .uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fuelux .input-prepend input,.fuelux .input-append input,.fuelux .input-prepend input[class*="span"],.fuelux .input-append input[class*="span"]{display:inline-block;width:auto}.fuelux .controls-row [class*="span"]+[class*="span"]{margin-left:0}.fuelux .modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.fuelux .modal.fade{top:-100px}.fuelux .modal.fade.in{top:20px}}@media(max-width:480px){.fuelux .nav-collapse{-webkit-transform:translate3d(0,0,0)}.fuelux .page-header h1 small{display:block;line-height:20px}.fuelux input[type="checkbox"],.fuelux input[type="radio"]{border:1px solid #ccc}.fuelux .form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.fuelux .form-horizontal .controls{margin-left:0}.fuelux .form-horizontal .control-list{padding-top:0}.fuelux .form-horizontal .form-actions{padding-right:10px;padding-left:10px}.fuelux .media .pull-left,.fuelux .media .pull-right{display:block;float:none;margin-bottom:10px}.fuelux .media-object{margin-right:0;margin-left:0}.fuelux .modal{top:10px;right:10px;left:10px}.fuelux .modal-header .close{padding:10px;margin:-10px}.fuelux .carousel-caption{position:static}}@media(max-width:979px){.fuelux body{padding-top:0}.fuelux .navbar-fixed-top,.fuelux .navbar-fixed-bottom{position:static}.fuelux .navbar-fixed-top{margin-bottom:20px}.fuelux .navbar-fixed-bottom{margin-top:20px}.fuelux .navbar-fixed-top .navbar-inner,.fuelux .navbar-fixed-bottom .navbar-inner{padding:5px}.fuelux .navbar .container{width:auto;padding:0}.fuelux .navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.fuelux .nav-collapse{clear:both}.fuelux .nav-collapse .nav{float:none;margin:0 0 10px}.fuelux .nav-collapse .nav>li{float:none}.fuelux .nav-collapse .nav>li>a{margin-bottom:2px}.fuelux .nav-collapse .nav>.divider-vertical{display:none}.fuelux .nav-collapse .nav .nav-header{color:#777;text-shadow:none}.fuelux .nav-collapse .nav>li>a,.fuelux .nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fuelux .nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux .nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.fuelux .nav-collapse .nav>li>a:hover,.fuelux .nav-collapse .nav>li>a:focus,.fuelux .nav-collapse .dropdown-menu a:hover,.fuelux .nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.fuelux .navbar-inverse .nav-collapse .nav>li>a,.fuelux .navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.fuelux .navbar-inverse .nav-collapse .nav>li>a:hover,.fuelux .navbar-inverse .nav-collapse .nav>li>a:focus,.fuelux .navbar-inverse .nav-collapse .dropdown-menu a:hover,.fuelux .navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.fuelux .nav-collapse.in .btn-group{padding:0;margin-top:5px}.fuelux .nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.fuelux .nav-collapse .open>.dropdown-menu{display:block}.fuelux .nav-collapse .dropdown-menu:before,.fuelux .nav-collapse .dropdown-menu:after{display:none}.fuelux .nav-collapse .dropdown-menu .divider{display:none}.fuelux .nav-collapse .nav>li>.dropdown-menu:before,.fuelux .nav-collapse .nav>li>.dropdown-menu:after{display:none}.fuelux .nav-collapse .navbar-form,.fuelux .nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.fuelux .navbar-inverse .nav-collapse .navbar-form,.fuelux .navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.fuelux .navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.fuelux .nav-collapse,.fuelux .nav-collapse.collapse{height:0;overflow:hidden}.fuelux .navbar .btn-navbar{display:block}.fuelux .navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.fuelux .nav-collapse.collapse{height:auto!important;overflow:visible!important}}
\ No newline at end of file
diff --git a/opendaylight/web/root/src/main/resources/css/fuelux.min.css b/opendaylight/web/root/src/main/resources/css/fuelux.min.css
new file mode 100755 (executable)
index 0000000..314f3dc
--- /dev/null
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap v2.3.2
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.fuelux .clearfix{*zoom:1}.fuelux .clearfix:before,.fuelux .clearfix:after{display:table;line-height:0;content:""}.fuelux .clearfix:after{clear:both}.fuelux .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.fuelux .input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fuelux article,.fuelux aside,.fuelux details,.fuelux figcaption,.fuelux figure,.fuelux footer,.fuelux header,.fuelux hgroup,.fuelux nav,.fuelux section{display:block}.fuelux audio,.fuelux canvas,.fuelux video{display:inline-block;*display:inline;*zoom:1}.fuelux audio:not([controls]){display:none}.fuelux html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}.fuelux a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.fuelux a:hover,.fuelux a:active{outline:0}.fuelux sub,.fuelux sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}.fuelux sup{top:-0.5em}.fuelux sub{bottom:-0.25em}.fuelux img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}.fuelux #map_canvas img,.fuelux .google-maps img{max-width:none}.fuelux button,.fuelux input,.fuelux select,.fuelux textarea{margin:0;font-size:100%;vertical-align:middle}.fuelux button,.fuelux input{*overflow:visible;line-height:normal}.fuelux button::-moz-focus-inner,.fuelux input::-moz-focus-inner{padding:0;border:0}.fuelux button,.fuelux html input[type="button"],.fuelux input[type="reset"],.fuelux input[type="submit"]{cursor:pointer;-webkit-appearance:button}.fuelux label,.fuelux select,.fuelux button,.fuelux input[type="button"],.fuelux input[type="reset"],.fuelux input[type="submit"],.fuelux input[type="radio"],.fuelux input[type="checkbox"]{cursor:pointer}.fuelux input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}.fuelux input[type="search"]::-webkit-search-decoration,.fuelux input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}.fuelux textarea{overflow:auto;vertical-align:top}@media print{.fuelux *{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}.fuelux a,.fuelux a:visited{text-decoration:underline}.fuelux a[href]:after{content:" (" attr(href) ")"}.fuelux abbr[title]:after{content:" (" attr(title) ")"}.fuelux .ir a:after,.fuelux a[href^="javascript:"]:after,.fuelux a[href^="#"]:after{content:""}.fuelux pre,.fuelux blockquote{border:1px solid #999;page-break-inside:avoid}.fuelux thead{display:table-header-group}.fuelux tr,.fuelux img{page-break-inside:avoid}.fuelux img{max-width:100%!important}@page{margin:.5cm}.fuelux p,.fuelux h2,.fuelux h3{widows:3;orphans:3}.fuelux h2,.fuelux h3{page-break-after:avoid}}.fuelux body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}.fuelux a{color:#08c;text-decoration:none}.fuelux a:hover,.fuelux a:focus{color:#005580;text-decoration:underline}.fuelux .img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.fuelux .img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.fuelux .img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.fuelux .row{margin-left:-20px;*zoom:1}.fuelux .row:before,.fuelux .row:after{display:table;line-height:0;content:""}.fuelux .row:after{clear:both}.fuelux [class*="span"]{float:left;min-height:1px;margin-left:20px}.fuelux .container,.fuelux .navbar-static-top .container,.fuelux .navbar-fixed-top .container,.fuelux .navbar-fixed-bottom .container{width:940px}.fuelux .span12{width:940px}.fuelux .span11{width:860px}.fuelux .span10{width:780px}.fuelux .span9{width:700px}.fuelux .span8{width:620px}.fuelux .span7{width:540px}.fuelux .span6{width:460px}.fuelux .span5{width:380px}.fuelux .span4{width:300px}.fuelux .span3{width:220px}.fuelux .span2{width:140px}.fuelux .span1{width:60px}.fuelux .offset12{margin-left:980px}.fuelux .offset11{margin-left:900px}.fuelux .offset10{margin-left:820px}.fuelux .offset9{margin-left:740px}.fuelux .offset8{margin-left:660px}.fuelux .offset7{margin-left:580px}.fuelux .offset6{margin-left:500px}.fuelux .offset5{margin-left:420px}.fuelux .offset4{margin-left:340px}.fuelux .offset3{margin-left:260px}.fuelux .offset2{margin-left:180px}.fuelux .offset1{margin-left:100px}.fuelux .row-fluid{width:100%;*zoom:1}.fuelux .row-fluid:before,.fuelux .row-fluid:after{display:table;line-height:0;content:""}.fuelux .row-fluid:after{clear:both}.fuelux .row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fuelux .row-fluid [class*="span"]:first-child{margin-left:0}.fuelux .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.fuelux .row-fluid .span12{width:100%;*width:99.94680851063829%}.fuelux .row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.fuelux .row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.fuelux .row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.fuelux .row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.fuelux .row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.fuelux .row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.fuelux .row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.fuelux .row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.fuelux .row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.fuelux .row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.fuelux .row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.fuelux .row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.fuelux .row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.fuelux .row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.fuelux .row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.fuelux .row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.fuelux .row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.fuelux .row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.fuelux .row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.fuelux .row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.fuelux .row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.fuelux .row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.fuelux .row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.fuelux .row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.fuelux .row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.fuelux .row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.fuelux .row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.fuelux .row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.fuelux .row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.fuelux .row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.fuelux .row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.fuelux .row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.fuelux .row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.fuelux .row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.fuelux .row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}.fuelux [class*="span"].hide,.fuelux .row-fluid [class*="span"].hide{display:none}.fuelux [class*="span"].pull-right,.fuelux .row-fluid [class*="span"].pull-right{float:right}.fuelux .container{margin-right:auto;margin-left:auto;*zoom:1}.fuelux .container:before,.fuelux .container:after{display:table;line-height:0;content:""}.fuelux .container:after{clear:both}.fuelux .container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.fuelux .container-fluid:before,.fuelux .container-fluid:after{display:table;line-height:0;content:""}.fuelux .container-fluid:after{clear:both}.fuelux p{margin:0 0 10px}.fuelux .lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}.fuelux small{font-size:85%}.fuelux strong{font-weight:bold}.fuelux em{font-style:italic}.fuelux cite{font-style:normal}.fuelux .muted{color:#999}.fuelux a.muted:hover,.fuelux a.muted:focus{color:#808080}.fuelux .text-warning{color:#c09853}.fuelux a.text-warning:hover,.fuelux a.text-warning:focus{color:#a47e3c}.fuelux .text-error{color:#b94a48}.fuelux a.text-error:hover,.fuelux a.text-error:focus{color:#953b39}.fuelux .text-info{color:#3a87ad}.fuelux a.text-info:hover,.fuelux a.text-info:focus{color:#2d6987}.fuelux .text-success{color:#468847}.fuelux a.text-success:hover,.fuelux a.text-success:focus{color:#356635}.fuelux .text-left{text-align:left}.fuelux .text-right{text-align:right}.fuelux .text-center{text-align:center}.fuelux h1,.fuelux h2,.fuelux h3,.fuelux h4,.fuelux h5,.fuelux h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}.fuelux h1 small,.fuelux h2 small,.fuelux h3 small,.fuelux h4 small,.fuelux h5 small,.fuelux h6 small{font-weight:normal;line-height:1;color:#999}.fuelux h1,.fuelux h2,.fuelux h3{line-height:40px}.fuelux h1{font-size:38.5px}.fuelux h2{font-size:31.5px}.fuelux h3{font-size:24.5px}.fuelux h4{font-size:17.5px}.fuelux h5{font-size:14px}.fuelux h6{font-size:11.9px}.fuelux h1 small{font-size:24.5px}.fuelux h2 small{font-size:17.5px}.fuelux h3 small{font-size:14px}.fuelux h4 small{font-size:14px}.fuelux .page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}.fuelux ul,.fuelux ol{padding:0;margin:0 0 10px 25px}.fuelux ul ul,.fuelux ul ol,.fuelux ol ol,.fuelux ol ul{margin-bottom:0}.fuelux li{line-height:20px}.fuelux ul.unstyled,.fuelux ol.unstyled{margin-left:0;list-style:none}.fuelux ul.inline,.fuelux ol.inline{margin-left:0;list-style:none}.fuelux ul.inline>li,.fuelux ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}.fuelux dl{margin-bottom:20px}.fuelux dt,.fuelux dd{line-height:20px}.fuelux dt{font-weight:bold}.fuelux dd{margin-left:10px}.fuelux .dl-horizontal{*zoom:1}.fuelux .dl-horizontal:before,.fuelux .dl-horizontal:after{display:table;line-height:0;content:""}.fuelux .dl-horizontal:after{clear:both}.fuelux .dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.fuelux .dl-horizontal dd{margin-left:180px}.fuelux hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}.fuelux abbr[title],.fuelux abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.fuelux abbr.initialism{font-size:90%;text-transform:uppercase}.fuelux blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}.fuelux blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}.fuelux blockquote small{display:block;line-height:20px;color:#999}.fuelux blockquote small:before{content:'\2014 \00A0'}.fuelux blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}.fuelux blockquote.pull-right p,.fuelux blockquote.pull-right small{text-align:right}.fuelux blockquote.pull-right small:before{content:''}.fuelux blockquote.pull-right small:after{content:'\00A0 \2014'}.fuelux q:before,.fuelux q:after,.fuelux blockquote:before,.fuelux blockquote:after{content:""}.fuelux address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}.fuelux code,.fuelux pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fuelux code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}.fuelux pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux pre.prettyprint{margin-bottom:20px}.fuelux pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.fuelux .pre-scrollable{max-height:340px;overflow-y:scroll}.fuelux form{margin:0 0 20px}.fuelux fieldset{padding:0;margin:0;border:0}.fuelux legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}.fuelux legend small{font-size:15px;color:#999}.fuelux label,.fuelux input,.fuelux button,.fuelux select,.fuelux textarea{font-size:14px;font-weight:normal;line-height:20px}.fuelux input,.fuelux button,.fuelux select,.fuelux textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.fuelux label{display:block;margin-bottom:5px}.fuelux select,.fuelux textarea,.fuelux input[type="text"],.fuelux input[type="password"],.fuelux input[type="datetime"],.fuelux input[type="datetime-local"],.fuelux input[type="date"],.fuelux input[type="month"],.fuelux input[type="time"],.fuelux input[type="week"],.fuelux input[type="number"],.fuelux input[type="email"],.fuelux input[type="url"],.fuelux input[type="search"],.fuelux input[type="tel"],.fuelux input[type="color"],.fuelux .uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux input,.fuelux textarea,.fuelux .uneditable-input{width:206px}.fuelux textarea{height:auto}.fuelux textarea,.fuelux input[type="text"],.fuelux input[type="password"],.fuelux input[type="datetime"],.fuelux input[type="datetime-local"],.fuelux input[type="date"],.fuelux input[type="month"],.fuelux input[type="time"],.fuelux input[type="week"],.fuelux input[type="number"],.fuelux input[type="email"],.fuelux input[type="url"],.fuelux input[type="search"],.fuelux input[type="tel"],.fuelux input[type="color"],.fuelux .uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}.fuelux textarea:focus,.fuelux input[type="text"]:focus,.fuelux input[type="password"]:focus,.fuelux input[type="datetime"]:focus,.fuelux input[type="datetime-local"]:focus,.fuelux input[type="date"]:focus,.fuelux input[type="month"]:focus,.fuelux input[type="time"]:focus,.fuelux input[type="week"]:focus,.fuelux input[type="number"]:focus,.fuelux input[type="email"]:focus,.fuelux input[type="url"]:focus,.fuelux input[type="search"]:focus,.fuelux input[type="tel"]:focus,.fuelux input[type="color"]:focus,.fuelux .uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}.fuelux input[type="radio"],.fuelux input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}.fuelux input[type="file"],.fuelux input[type="image"],.fuelux input[type="submit"],.fuelux input[type="reset"],.fuelux input[type="button"],.fuelux input[type="radio"],.fuelux input[type="checkbox"]{width:auto}.fuelux select,.fuelux input[type="file"]{height:30px;*margin-top:4px;line-height:30px}.fuelux select{width:220px;background-color:#fff;border:1px solid #ccc}.fuelux select[multiple],.fuelux select[size]{height:auto}.fuelux select:focus,.fuelux input[type="file"]:focus,.fuelux input[type="radio"]:focus,.fuelux input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.fuelux .uneditable-input,.fuelux .uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.fuelux .uneditable-input{overflow:hidden;white-space:nowrap}.fuelux .uneditable-textarea{width:auto;height:auto}.fuelux input:-moz-placeholder,.fuelux textarea:-moz-placeholder{color:#999}.fuelux input:-ms-input-placeholder,.fuelux textarea:-ms-input-placeholder{color:#999}.fuelux input::-webkit-input-placeholder,.fuelux textarea::-webkit-input-placeholder{color:#999}.fuelux .radio,.fuelux .checkbox{min-height:20px;padding-left:20px}.fuelux .radio input[type="radio"],.fuelux .checkbox input[type="checkbox"]{float:left;margin-left:-20px}.fuelux .controls>.radio:first-child,.fuelux .controls>.checkbox:first-child{padding-top:5px}.fuelux .radio.inline,.fuelux .checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.fuelux .radio.inline+.radio.inline,.fuelux .checkbox.inline+.checkbox.inline{margin-left:10px}.fuelux .input-mini{width:60px}.fuelux .input-small{width:90px}.fuelux .input-medium{width:150px}.fuelux .input-large{width:210px}.fuelux .input-xlarge{width:270px}.fuelux .input-xxlarge{width:530px}.fuelux input[class*="span"],.fuelux select[class*="span"],.fuelux textarea[class*="span"],.fuelux .uneditable-input[class*="span"],.fuelux .row-fluid input[class*="span"],.fuelux .row-fluid select[class*="span"],.fuelux .row-fluid textarea[class*="span"],.fuelux .row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.fuelux .input-append input[class*="span"],.fuelux .input-append .uneditable-input[class*="span"],.fuelux .input-prepend input[class*="span"],.fuelux .input-prepend .uneditable-input[class*="span"],.fuelux .row-fluid input[class*="span"],.fuelux .row-fluid select[class*="span"],.fuelux .row-fluid textarea[class*="span"],.fuelux .row-fluid .uneditable-input[class*="span"],.fuelux .row-fluid .input-prepend [class*="span"],.fuelux .row-fluid .input-append [class*="span"]{display:inline-block}.fuelux input,.fuelux textarea,.fuelux .uneditable-input{margin-left:0}.fuelux .controls-row [class*="span"]+[class*="span"]{margin-left:20px}.fuelux input.span12,textarea.span12,.uneditable-input.span12{width:926px}.fuelux input.span11,textarea.span11,.uneditable-input.span11{width:846px}.fuelux input.span10,textarea.span10,.uneditable-input.span10{width:766px}.fuelux input.span9,textarea.span9,.uneditable-input.span9{width:686px}.fuelux input.span8,textarea.span8,.uneditable-input.span8{width:606px}.fuelux input.span7,textarea.span7,.uneditable-input.span7{width:526px}.fuelux input.span6,textarea.span6,.uneditable-input.span6{width:446px}.fuelux input.span5,textarea.span5,.uneditable-input.span5{width:366px}.fuelux input.span4,textarea.span4,.uneditable-input.span4{width:286px}.fuelux input.span3,textarea.span3,.uneditable-input.span3{width:206px}.fuelux input.span2,textarea.span2,.uneditable-input.span2{width:126px}.fuelux input.span1,textarea.span1,.uneditable-input.span1{width:46px}.fuelux .controls-row{*zoom:1}.fuelux .controls-row:before,.fuelux .controls-row:after{display:table;line-height:0;content:""}.fuelux .controls-row:after{clear:both}.fuelux .controls-row [class*="span"],.fuelux .row-fluid .controls-row [class*="span"]{float:left}.fuelux .controls-row .checkbox[class*="span"],.fuelux .controls-row .radio[class*="span"]{padding-top:5px}.fuelux input[disabled],.fuelux select[disabled],.fuelux textarea[disabled],.fuelux input[readonly],.fuelux select[readonly],.fuelux textarea[readonly]{cursor:not-allowed;background-color:#eee}.fuelux input[type="radio"][disabled],.fuelux input[type="checkbox"][disabled],.fuelux input[type="radio"][readonly],.fuelux input[type="checkbox"][readonly]{background-color:transparent}.fuelux .control-group.warning .control-label,.fuelux .control-group.warning .help-block,.fuelux .control-group.warning .help-inline{color:#c09853}.fuelux .control-group.warning .checkbox,.fuelux .control-group.warning .radio,.fuelux .control-group.warning input,.fuelux .control-group.warning select,.fuelux .control-group.warning textarea{color:#c09853}.fuelux .control-group.warning input,.fuelux .control-group.warning select,.fuelux .control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.fuelux .control-group.warning input:focus,.fuelux .control-group.warning select:focus,.fuelux .control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.fuelux .control-group.warning .input-prepend .add-on,.fuelux .control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.fuelux .control-group.error .control-label,.fuelux .control-group.error .help-block,.fuelux .control-group.error .help-inline{color:#b94a48}.fuelux .control-group.error .checkbox,.fuelux .control-group.error .radio,.fuelux .control-group.error input,.fuelux .control-group.error select,.fuelux .control-group.error textarea{color:#b94a48}.fuelux .control-group.error input,.fuelux .control-group.error select,.fuelux .control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.fuelux .control-group.error input:focus,.fuelux .control-group.error select:focus,.fuelux .control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.fuelux .control-group.error .input-prepend .add-on,.fuelux .control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.fuelux .control-group.success .control-label,.fuelux .control-group.success .help-block,.fuelux .control-group.success .help-inline{color:#468847}.fuelux .control-group.success .checkbox,.fuelux .control-group.success .radio,.fuelux .control-group.success input,.fuelux .control-group.success select,.fuelux .control-group.success textarea{color:#468847}.fuelux .control-group.success input,.fuelux .control-group.success select,.fuelux .control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.fuelux .control-group.success input:focus,.fuelux .control-group.success select:focus,.fuelux .control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.fuelux .control-group.success .input-prepend .add-on,.fuelux .control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.fuelux .control-group.info .control-label,.fuelux .control-group.info .help-block,.fuelux .control-group.info .help-inline{color:#3a87ad}.fuelux .control-group.info .checkbox,.fuelux .control-group.info .radio,.fuelux .control-group.info input,.fuelux .control-group.info select,.fuelux .control-group.info textarea{color:#3a87ad}.fuelux .control-group.info input,.fuelux .control-group.info select,.fuelux .control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.fuelux .control-group.info input:focus,.fuelux .control-group.info select:focus,.fuelux .control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.fuelux .control-group.info .input-prepend .add-on,.fuelux .control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}.fuelux input:focus:invalid,.fuelux textarea:focus:invalid,.fuelux select:focus:invalid{color:#b94a48;border-color:#ee5f5b}.fuelux input:focus:invalid:focus,.fuelux textarea:focus:invalid:focus,.fuelux select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.fuelux .form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.fuelux .form-actions:before,.fuelux .form-actions:after{display:table;line-height:0;content:""}.fuelux .form-actions:after{clear:both}.fuelux .help-block,.fuelux .help-inline{color:#595959}.fuelux .help-block{display:block;margin-bottom:10px}.fuelux .help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.fuelux .input-append,.fuelux .input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.fuelux .input-append input,.fuelux .input-prepend input,.fuelux .input-append select,.fuelux .input-prepend select,.fuelux .input-append .uneditable-input,.fuelux .input-prepend .uneditable-input,.fuelux .input-append .dropdown-menu,.fuelux .input-prepend .dropdown-menu,.fuelux .input-append .popover,.fuelux .input-prepend .popover{font-size:14px}.fuelux .input-append input,.fuelux .input-prepend input,.fuelux .input-append select,.fuelux .input-prepend select,.fuelux .input-append .uneditable-input,.fuelux .input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.fuelux .input-append input:focus,.fuelux .input-prepend input:focus,.fuelux .input-append select:focus,.fuelux .input-prepend select:focus,.fuelux .input-append .uneditable-input:focus,.fuelux .input-prepend .uneditable-input:focus{z-index:2}.fuelux .input-append .add-on,.fuelux .input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.fuelux .input-append .add-on,.fuelux .input-prepend .add-on,.fuelux .input-append .btn,.fuelux .input-prepend .btn,.fuelux .input-append .btn-group>.dropdown-toggle,.fuelux .input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .input-append .active,.fuelux .input-prepend .active{background-color:#a9dba9;border-color:#46a546}.fuelux .input-prepend .add-on,.fuelux .input-prepend .btn{margin-right:-1px}.fuelux .input-prepend .add-on:first-child,.fuelux .input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.fuelux .input-append input,.fuelux .input-append select,.fuelux .input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.fuelux .input-append input+.btn-group .btn:last-child,.fuelux .input-append select+.btn-group .btn:last-child,.fuelux .input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.fuelux .input-append .add-on,.fuelux .input-append .btn,.fuelux .input-append .btn-group{margin-left:-1px}.fuelux .input-append .add-on:last-child,.fuelux .input-append .btn:last-child,.fuelux .input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.fuelux .input-prepend.input-append input,.fuelux .input-prepend.input-append select,.fuelux .input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .input-prepend.input-append input+.btn-group .btn,.fuelux .input-prepend.input-append select+.btn-group .btn,.fuelux .input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.fuelux .input-prepend.input-append .add-on:first-child,.fuelux .input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.fuelux .input-prepend.input-append .add-on:last-child,.fuelux .input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.fuelux .input-prepend.input-append .btn-group:first-child{margin-left:0}.fuelux input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.fuelux .form-search .input-append .search-query,.fuelux .form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.fuelux .form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.fuelux .form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.fuelux .form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.fuelux .form-search input,.fuelux .form-inline input,.fuelux .form-horizontal input,.fuelux .form-search textarea,.fuelux .form-inline textarea,.fuelux .form-horizontal textarea,.fuelux .form-search select,.fuelux .form-inline select,.fuelux .form-horizontal select,.fuelux .form-search .help-inline,.fuelux .form-inline .help-inline,.fuelux .form-horizontal .help-inline,.fuelux .form-search .uneditable-input,.fuelux .form-inline .uneditable-input,.fuelux .form-horizontal .uneditable-input,.fuelux .form-search .input-prepend,.fuelux .form-inline .input-prepend,.fuelux .form-horizontal .input-prepend,.fuelux .form-search .input-append,.fuelux .form-inline .input-append,.fuelux .form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.fuelux .form-search .hide,.fuelux .form-inline .hide,.fuelux .form-horizontal .hide{display:none}.fuelux .form-search label,.fuelux .form-inline label,.fuelux .form-search .btn-group,.fuelux .form-inline .btn-group{display:inline-block}.fuelux .form-search .input-append,.fuelux .form-inline .input-append,.fuelux .form-search .input-prepend,.fuelux .form-inline .input-prepend{margin-bottom:0}.fuelux .form-search .radio,.fuelux .form-search .checkbox,.fuelux .form-inline .radio,.fuelux .form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.fuelux .form-search .radio input[type="radio"],.fuelux .form-search .checkbox input[type="checkbox"],.fuelux .form-inline .radio input[type="radio"],.fuelux .form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.fuelux .control-group{margin-bottom:10px}.fuelux legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.fuelux .form-horizontal .control-group{margin-bottom:20px;*zoom:1}.fuelux .form-horizontal .control-group:before,.fuelux .form-horizontal .control-group:after{display:table;line-height:0;content:""}.fuelux .form-horizontal .control-group:after{clear:both}.fuelux .form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.fuelux .form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.fuelux .form-horizontal .controls:first-child{*padding-left:180px}.fuelux .form-horizontal .help-block{margin-bottom:0}.fuelux .form-horizontal input+.help-block,.fuelux .form-horizontal select+.help-block,.fuelux .form-horizontal textarea+.help-block,.fuelux .form-horizontal .uneditable-input+.help-block,.fuelux .form-horizontal .input-prepend+.help-block,.fuelux .form-horizontal .input-append+.help-block{margin-top:10px}.fuelux .form-horizontal .form-actions{padding-left:180px}.fuelux table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.fuelux .table{width:100%;margin-bottom:20px}.fuelux .table th,.fuelux .table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.fuelux .table th{font-weight:bold}.fuelux .table thead th{vertical-align:bottom}.fuelux .table caption+thead tr:first-child th,.fuelux .table caption+thead tr:first-child td,.fuelux .table colgroup+thead tr:first-child th,.fuelux .table colgroup+thead tr:first-child td,.fuelux .table thead:first-child tr:first-child th,.fuelux .table thead:first-child tr:first-child td{border-top:0}.fuelux .table tbody+tbody{border-top:2px solid #ddd}.fuelux .table .table{background-color:#fff}.fuelux .table-condensed th,.fuelux .table-condensed td{padding:4px 5px}.fuelux .table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux .table-bordered th,.fuelux .table-bordered td{border-left:1px solid #ddd}.fuelux .table-bordered caption+thead tr:first-child th,.fuelux .table-bordered caption+tbody tr:first-child th,.fuelux .table-bordered caption+tbody tr:first-child td,.fuelux .table-bordered colgroup+thead tr:first-child th,.fuelux .table-bordered colgroup+tbody tr:first-child th,.fuelux .table-bordered colgroup+tbody tr:first-child td,.fuelux .table-bordered thead:first-child tr:first-child th,.fuelux .table-bordered tbody:first-child tr:first-child th,.fuelux .table-bordered tbody:first-child tr:first-child td{border-top:0}.fuelux .table-bordered thead:first-child tr:first-child>th:first-child,.fuelux .table-bordered tbody:first-child tr:first-child>td:first-child,.fuelux .table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.fuelux .table-bordered thead:first-child tr:first-child>th:last-child,.fuelux .table-bordered tbody:first-child tr:first-child>td:last-child,.fuelux .table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.fuelux .table-bordered thead:last-child tr:last-child>th:first-child,.fuelux .table-bordered tbody:last-child tr:last-child>td:first-child,.fuelux .table-bordered tbody:last-child tr:last-child>th:first-child,.fuelux .table-bordered tfoot:last-child tr:last-child>td:first-child,.fuelux .table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.fuelux .table-bordered thead:last-child tr:last-child>th:last-child,.fuelux .table-bordered tbody:last-child tr:last-child>td:last-child,.fuelux .table-bordered tbody:last-child tr:last-child>th:last-child,.fuelux .table-bordered tfoot:last-child tr:last-child>td:last-child,.fuelux .table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.fuelux .table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.fuelux .table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.fuelux .table-bordered caption+thead tr:first-child th:first-child,.fuelux .table-bordered caption+tbody tr:first-child td:first-child,.fuelux .table-bordered colgroup+thead tr:first-child th:first-child,.fuelux .table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.fuelux .table-bordered caption+thead tr:first-child th:last-child,.fuelux .table-bordered caption+tbody tr:first-child td:last-child,.fuelux .table-bordered colgroup+thead tr:first-child th:last-child,.fuelux .table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.fuelux .table-striped tbody>tr:nth-child(odd)>td,.fuelux .table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.fuelux .table-hover tbody tr:hover>td,.fuelux .table-hover tbody tr:hover>th{background-color:#f5f5f5}.fuelux table td[class*="span"],.fuelux table th[class*="span"],.fuelux .row-fluid table td[class*="span"],.fuelux .row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.fuelux .table td.span1,.fuelux .table th.span1{float:none;width:44px;margin-left:0}.fuelux .table td.span2,.fuelux .table th.span2{float:none;width:124px;margin-left:0}.fuelux .table td.span3,.fuelux .table th.span3{float:none;width:204px;margin-left:0}.fuelux .table td.span4,.fuelux .table th.span4{float:none;width:284px;margin-left:0}.fuelux .table td.span5,.fuelux .table th.span5{float:none;width:364px;margin-left:0}.fuelux .table td.span6,.fuelux .table th.span6{float:none;width:444px;margin-left:0}.fuelux .table td.span7,.fuelux .table th.span7{float:none;width:524px;margin-left:0}.fuelux .table td.span8,.fuelux .table th.span8{float:none;width:604px;margin-left:0}.fuelux .table td.span9,.fuelux .table th.span9{float:none;width:684px;margin-left:0}.fuelux .table td.span10,.fuelux .table th.span10{float:none;width:764px;margin-left:0}.fuelux .table td.span11,.fuelux .table th.span11{float:none;width:844px;margin-left:0}.fuelux .table td.span12,.fuelux .table th.span12{float:none;width:924px;margin-left:0}.fuelux .table tbody tr.success>td{background-color:#dff0d8}.fuelux .table tbody tr.error>td{background-color:#f2dede}.fuelux .table tbody tr.warning>td{background-color:#fcf8e3}.fuelux .table tbody tr.info>td{background-color:#d9edf7}.fuelux .table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.fuelux .table-hover tbody tr.error:hover>td{background-color:#ebcccc}.fuelux .table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.fuelux .table-hover tbody tr.info:hover>td{background-color:#c4e3f3}.fuelux [class^="icon-"],.fuelux [class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.fuelux .icon-white,.fuelux .nav-pills>.active>a>[class^="icon-"],.fuelux .nav-pills>.active>a>[class*=" icon-"],.fuelux .nav-list>.active>a>[class^="icon-"],.fuelux .nav-list>.active>a>[class*=" icon-"],.fuelux .navbar-inverse .nav>.active>a>[class^="icon-"],.fuelux .navbar-inverse .nav>.active>a>[class*=" icon-"],.fuelux .dropdown-menu>li>a:hover>[class^="icon-"],.fuelux .dropdown-menu>li>a:focus>[class^="icon-"],.fuelux .dropdown-menu>li>a:hover>[class*=" icon-"],.fuelux .dropdown-menu>li>a:focus>[class*=" icon-"],.fuelux .dropdown-menu>.active>a>[class^="icon-"],.fuelux .dropdown-menu>.active>a>[class*=" icon-"],.fuelux .dropdown-submenu:hover>a>[class^="icon-"],.fuelux .dropdown-submenu:focus>a>[class^="icon-"],.fuelux .dropdown-submenu:hover>a>[class*=" icon-"],.fuelux .dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.fuelux .icon-glass{background-position:0 0}.fuelux .icon-music{background-position:-24px 0}.fuelux .icon-search{background-position:-48px 0}.fuelux .icon-envelope{background-position:-72px 0}.fuelux .icon-heart{background-position:-96px 0}.fuelux .icon-star{background-position:-120px 0}.fuelux .icon-star-empty{background-position:-144px 0}.fuelux .icon-user{background-position:-168px 0}.fuelux .icon-film{background-position:-192px 0}.fuelux .icon-th-large{background-position:-216px 0}.fuelux .icon-th{background-position:-240px 0}.fuelux .icon-th-list{background-position:-264px 0}.fuelux .icon-ok{background-position:-288px 0}.fuelux .icon-remove{background-position:-312px 0}.fuelux .icon-zoom-in{background-position:-336px 0}.fuelux .icon-zoom-out{background-position:-360px 0}.fuelux .icon-off{background-position:-384px 0}.fuelux .icon-signal{background-position:-408px 0}.fuelux .icon-cog{background-position:-432px 0}.fuelux .icon-trash{background-position:-456px 0}.fuelux .icon-home{background-position:0 -24px}.fuelux .icon-file{background-position:-24px -24px}.fuelux .icon-time{background-position:-48px -24px}.fuelux .icon-road{background-position:-72px -24px}.fuelux .icon-download-alt{background-position:-96px -24px}.fuelux .icon-download{background-position:-120px -24px}.fuelux .icon-upload{background-position:-144px -24px}.fuelux .icon-inbox{background-position:-168px -24px}.fuelux .icon-play-circle{background-position:-192px -24px}.fuelux .icon-repeat{background-position:-216px -24px}.fuelux .icon-refresh{background-position:-240px -24px}.fuelux .icon-list-alt{background-position:-264px -24px}.fuelux .icon-lock{background-position:-287px -24px}.fuelux .icon-flag{background-position:-312px -24px}.fuelux .icon-headphones{background-position:-336px -24px}.fuelux .icon-volume-off{background-position:-360px -24px}.fuelux .icon-volume-down{background-position:-384px -24px}.fuelux .icon-volume-up{background-position:-408px -24px}.fuelux .icon-qrcode{background-position:-432px -24px}.fuelux .icon-barcode{background-position:-456px -24px}.fuelux .icon-tag{background-position:0 -48px}.fuelux .icon-tags{background-position:-25px -48px}.fuelux .icon-book{background-position:-48px -48px}.fuelux .icon-bookmark{background-position:-72px -48px}.fuelux .icon-print{background-position:-96px -48px}.fuelux .icon-camera{background-position:-120px -48px}.fuelux .icon-font{background-position:-144px -48px}.fuelux .icon-bold{background-position:-167px -48px}.fuelux .icon-italic{background-position:-192px -48px}.fuelux .icon-text-height{background-position:-216px -48px}.fuelux .icon-text-width{background-position:-240px -48px}.fuelux .icon-align-left{background-position:-264px -48px}.fuelux .icon-align-center{background-position:-288px -48px}.fuelux .icon-align-right{background-position:-312px -48px}.fuelux .icon-align-justify{background-position:-336px -48px}.fuelux .icon-list{background-position:-360px -48px}.fuelux .icon-indent-left{background-position:-384px -48px}.fuelux .icon-indent-right{background-position:-408px -48px}.fuelux .icon-facetime-video{background-position:-432px -48px}.fuelux .icon-picture{background-position:-456px -48px}.fuelux .icon-pencil{background-position:0 -72px}.fuelux .icon-map-marker{background-position:-24px -72px}.fuelux .icon-adjust{background-position:-48px -72px}.fuelux .icon-tint{background-position:-72px -72px}.fuelux .icon-edit{background-position:-96px -72px}.fuelux .icon-share{background-position:-120px -72px}.fuelux .icon-check{background-position:-144px -72px}.fuelux .icon-move{background-position:-168px -72px}.fuelux .icon-step-backward{background-position:-192px -72px}.fuelux .icon-fast-backward{background-position:-216px -72px}.fuelux .icon-backward{background-position:-240px -72px}.fuelux .icon-play{background-position:-264px -72px}.fuelux .icon-pause{background-position:-288px -72px}.fuelux .icon-stop{background-position:-312px -72px}.fuelux .icon-forward{background-position:-336px -72px}.fuelux .icon-fast-forward{background-position:-360px -72px}.fuelux .icon-step-forward{background-position:-384px -72px}.fuelux .icon-eject{background-position:-408px -72px}.fuelux .icon-chevron-left{background-position:-432px -72px}.fuelux .icon-chevron-right{background-position:-456px -72px}.fuelux .icon-plus-sign{background-position:0 -96px}.fuelux .icon-minus-sign{background-position:-24px -96px}.fuelux .icon-remove-sign{background-position:-48px -96px}.fuelux .icon-ok-sign{background-position:-72px -96px}.fuelux .icon-question-sign{background-position:-96px -96px}.fuelux .icon-info-sign{background-position:-120px -96px}.fuelux .icon-screenshot{background-position:-144px -96px}.fuelux .icon-remove-circle{background-position:-168px -96px}.fuelux .icon-ok-circle{background-position:-192px -96px}.fuelux .icon-ban-circle{background-position:-216px -96px}.fuelux .icon-arrow-left{background-position:-240px -96px}.fuelux .icon-arrow-right{background-position:-264px -96px}.fuelux .icon-arrow-up{background-position:-289px -96px}.fuelux .icon-arrow-down{background-position:-312px -96px}.fuelux .icon-share-alt{background-position:-336px -96px}.fuelux .icon-resize-full{background-position:-360px -96px}.fuelux .icon-resize-small{background-position:-384px -96px}.fuelux .icon-plus{background-position:-408px -96px}.fuelux .icon-minus{background-position:-433px -96px}.fuelux .icon-asterisk{background-position:-456px -96px}.fuelux .icon-exclamation-sign{background-position:0 -120px}.fuelux .icon-gift{background-position:-24px -120px}.fuelux .icon-leaf{background-position:-48px -120px}.fuelux .icon-fire{background-position:-72px -120px}.fuelux .icon-eye-open{background-position:-96px -120px}.fuelux .icon-eye-close{background-position:-120px -120px}.fuelux .icon-warning-sign{background-position:-144px -120px}.fuelux .icon-plane{background-position:-168px -120px}.fuelux .icon-calendar{background-position:-192px -120px}.fuelux .icon-random{width:16px;background-position:-216px -120px}.fuelux .icon-comment{background-position:-240px -120px}.fuelux .icon-magnet{background-position:-264px -120px}.fuelux .icon-chevron-up{background-position:-288px -120px}.fuelux .icon-chevron-down{background-position:-313px -119px}.fuelux .icon-retweet{background-position:-336px -120px}.fuelux .icon-shopping-cart{background-position:-360px -120px}.fuelux .icon-folder-close{width:16px;background-position:-384px -120px}.fuelux .icon-folder-open{width:16px;background-position:-408px -120px}.fuelux .icon-resize-vertical{background-position:-432px -119px}.fuelux .icon-resize-horizontal{background-position:-456px -118px}.fuelux .icon-hdd{background-position:0 -144px}.fuelux .icon-bullhorn{background-position:-24px -144px}.fuelux .icon-bell{background-position:-48px -144px}.fuelux .icon-certificate{background-position:-72px -144px}.fuelux .icon-thumbs-up{background-position:-96px -144px}.fuelux .icon-thumbs-down{background-position:-120px -144px}.fuelux .icon-hand-right{background-position:-144px -144px}.fuelux .icon-hand-left{background-position:-168px -144px}.fuelux .icon-hand-up{background-position:-192px -144px}.fuelux .icon-hand-down{background-position:-216px -144px}.fuelux .icon-circle-arrow-right{background-position:-240px -144px}.fuelux .icon-circle-arrow-left{background-position:-264px -144px}.fuelux .icon-circle-arrow-up{background-position:-288px -144px}.fuelux .icon-circle-arrow-down{background-position:-312px -144px}.fuelux .icon-globe{background-position:-336px -144px}.fuelux .icon-wrench{background-position:-360px -144px}.fuelux .icon-tasks{background-position:-384px -144px}.fuelux .icon-filter{background-position:-408px -144px}.fuelux .icon-briefcase{background-position:-432px -144px}.fuelux .icon-fullscreen{background-position:-456px -144px}.fuelux .dropup,.fuelux .dropdown{position:relative}.fuelux .dropdown-toggle{*margin-bottom:-3px}.fuelux .dropdown-toggle:active,.fuelux .open .dropdown-toggle{outline:0}.fuelux .caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.fuelux .dropdown .caret{margin-top:8px;margin-left:2px}.fuelux .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.fuelux .dropdown-menu.pull-right{right:0;left:auto}.fuelux .dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.fuelux .dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.fuelux .dropdown-menu>li>a:hover,.fuelux .dropdown-menu>li>a:focus,.fuelux .dropdown-submenu:hover>a,.fuelux .dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.fuelux .dropdown-menu>.active>a,.fuelux .dropdown-menu>.active>a:hover,.fuelux .dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.fuelux .dropdown-menu>.disabled>a,.fuelux .dropdown-menu>.disabled>a:hover,.fuelux .dropdown-menu>.disabled>a:focus{color:#999}.fuelux .dropdown-menu>.disabled>a:hover,.fuelux .dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.fuelux .open{*z-index:1000}.fuelux .open>.dropdown-menu{display:block}.fuelux .dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.fuelux .pull-right>.dropdown-menu{right:0;left:auto}.fuelux .dropup .caret,.fuelux .navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.fuelux .dropup .dropdown-menu,.fuelux .navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.fuelux .dropdown-submenu{position:relative}.fuelux .dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.fuelux .dropdown-submenu:hover>.dropdown-menu{display:block}.fuelux .dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.fuelux .dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.fuelux .dropdown-submenu:hover>a:after{border-left-color:#fff}.fuelux .dropdown-submenu.pull-left{float:none}.fuelux .dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.fuelux .dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.fuelux .typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.fuelux .well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.fuelux .well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.fuelux .well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fuelux .fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fuelux .fade.in{opacity:1}.fuelux .collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.fuelux .collapse.in{height:auto}.fuelux .close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.fuelux .close:hover,.fuelux .close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}.fuelux button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.fuelux .btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.fuelux .btn:hover,.fuelux .btn:focus,.fuelux .btn:active,.fuelux .btn.active,.fuelux .btn.disabled,.fuelux .btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.fuelux .btn:active,.fuelux .btn.active{background-color:#ccc \9}.fuelux .btn:first-child{*margin-left:0}.fuelux .btn:hover,.fuelux .btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fuelux .btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.fuelux .btn.active,.fuelux .btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.fuelux .btn.disabled,.fuelux .btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.fuelux .btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.fuelux .btn-large [class^="icon-"],.fuelux .btn-large [class*=" icon-"]{margin-top:4px}.fuelux .btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fuelux .btn-small [class^="icon-"],.fuelux .btn-small [class*=" icon-"]{margin-top:0}.fuelux .btn-mini [class^="icon-"],.fuelux .btn-mini [class*=" icon-"]{margin-top:-1px}.fuelux .btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fuelux .btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fuelux .btn-block+.btn-block{margin-top:5px}.fuelux input[type="submit"].btn-block,.fuelux input[type="reset"].btn-block,.fuelux input[type="button"].btn-block{width:100%}.fuelux .btn-primary.active,.fuelux .btn-warning.active,.fuelux .btn-danger.active,.fuelux .btn-success.active,.fuelux .btn-info.active,.fuelux .btn-inverse.active{color:rgba(255,255,255,0.75)}.fuelux .btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-image:-moz-linear-gradient(top,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.fuelux .btn-primary:hover,.fuelux .btn-primary:focus,.fuelux .btn-primary:active,.fuelux .btn-primary.active,.fuelux .btn-primary.disabled,.fuelux .btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.fuelux .btn-primary:active,.fuelux .btn-primary.active{background-color:#039 \9}.fuelux .btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.fuelux .btn-warning:hover,.fuelux .btn-warning:focus,.fuelux .btn-warning:active,.fuelux .btn-warning.active,.fuelux .btn-warning.disabled,.fuelux .btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.fuelux .btn-warning:active,.fuelux .btn-warning.active{background-color:#c67605 \9}.fuelux .btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.fuelux .btn-danger:hover,.fuelux .btn-danger:focus,.fuelux .btn-danger:active,.fuelux .btn-danger.active,.fuelux .btn-danger.disabled,.fuelux .btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.fuelux .btn-danger:active,.fuelux .btn-danger.active{background-color:#942a25 \9}.fuelux .btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-image:-moz-linear-gradient(top,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.fuelux .btn-success:hover,.fuelux .btn-success:focus,.fuelux .btn-success:active,.fuelux .btn-success.active,.fuelux .btn-success.disabled,.fuelux .btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.fuelux .btn-success:active,.fuelux .btn-success.active{background-color:#408140 \9}.fuelux .btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.fuelux .btn-info:hover,.fuelux .btn-info:focus,.fuelux .btn-info:active,.fuelux .btn-info.active,.fuelux .btn-info.disabled,.fuelux .btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.fuelux .btn-info:active,.fuelux .btn-info.active{background-color:#24748c \9}.fuelux .btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-image:-moz-linear-gradient(top,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.fuelux .btn-inverse:hover,.fuelux .btn-inverse:focus,.fuelux .btn-inverse:active,.fuelux .btn-inverse.active,.fuelux .btn-inverse.disabled,.fuelux .btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.fuelux .btn-inverse:active,.fuelux .btn-inverse.active{background-color:#080808 \9}.fuelux button.btn,.fuelux input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}.fuelux button.btn::-moz-focus-inner,.fuelux input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}.fuelux button.btn.btn-large,.fuelux input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}.fuelux button.btn.btn-small,.fuelux input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}.fuelux button.btn.btn-mini,.fuelux input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.fuelux .btn-link,.fuelux .btn-link:active,.fuelux .btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.fuelux .btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .btn-link:hover,.fuelux .btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.fuelux .btn-link[disabled]:hover,.fuelux .btn-link[disabled]:focus{color:#333;text-decoration:none}.fuelux .btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.fuelux .btn-group:first-child{*margin-left:0}.fuelux .btn-group+.btn-group{margin-left:5px}.fuelux .btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.fuelux .btn-toolbar>.btn+.btn,.fuelux .btn-toolbar>.btn-group+.btn,.fuelux .btn-toolbar>.btn+.btn-group{margin-left:5px}.fuelux .btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .btn-group>.btn+.btn{margin-left:-1px}.fuelux .btn-group>.btn,.fuelux .btn-group>.dropdown-menu,.fuelux .btn-group>.popover{font-size:14px}.fuelux .btn-group>.btn-mini{font-size:10.5px}.fuelux .btn-group>.btn-small{font-size:11.9px}.fuelux .btn-group>.btn-large{font-size:17.5px}.fuelux .btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.fuelux .btn-group>.btn:last-child,.fuelux .btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.fuelux .btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.fuelux .btn-group>.btn.large:last-child,.fuelux .btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.fuelux .btn-group>.btn:hover,.fuelux .btn-group>.btn:focus,.fuelux .btn-group>.btn:active,.fuelux .btn-group>.btn.active{z-index:2}.fuelux .btn-group .dropdown-toggle:active,.fuelux .btn-group.open .dropdown-toggle{outline:0}.fuelux .btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.fuelux .btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.fuelux .btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.fuelux .btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.fuelux .btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.fuelux .btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.fuelux .btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.fuelux .btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.fuelux .btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.fuelux .btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.fuelux .btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.fuelux .btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.fuelux .btn .caret{margin-top:8px;margin-left:0}.fuelux .btn-large .caret{margin-top:6px}.fuelux .btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.fuelux .btn-mini .caret,.fuelux .btn-small .caret{margin-top:8px}.fuelux .dropup .btn-large .caret{border-bottom-width:5px}.fuelux .btn-primary .caret,.fuelux .btn-warning .caret,.fuelux .btn-danger .caret,.fuelux .btn-info .caret,.fuelux .btn-success .caret,.fuelux .btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.fuelux .btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.fuelux .btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.fuelux .btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.fuelux .btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.fuelux .btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.fuelux .btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.fuelux .alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux .alert,.fuelux .alert h4{color:#c09853}.fuelux .alert h4{margin:0}.fuelux .alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.fuelux .alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.fuelux .alert-success h4{color:#468847}.fuelux .alert-danger,.fuelux .alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.fuelux .alert-danger h4,.fuelux .alert-error h4{color:#b94a48}.fuelux .alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.fuelux .alert-info h4{color:#3a87ad}.fuelux .alert-block{padding-top:14px;padding-bottom:14px}.fuelux .alert-block>p,.fuelux .alert-block>ul{margin-bottom:0}.fuelux .alert-block p+p{margin-top:5px}.fuelux .nav{margin-bottom:20px;margin-left:0;list-style:none}.fuelux .nav>li>a{display:block}.fuelux .nav>li>a:hover,.fuelux .nav>li>a:focus{text-decoration:none;background-color:#eee}.fuelux .nav>li>a>img{max-width:none}.fuelux .nav>.pull-right{float:right}.fuelux .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.fuelux .nav li+.nav-header{margin-top:9px}.fuelux .nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.fuelux .nav-list>li>a,.fuelux .nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.fuelux .nav-list>li>a{padding:3px 15px}.fuelux .nav-list>.active>a,.fuelux .nav-list>.active>a:hover,.fuelux .nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.fuelux .nav-list [class^="icon-"],.fuelux .nav-list [class*=" icon-"]{margin-right:2px}.fuelux .nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.fuelux .nav-tabs,.fuelux .nav-pills{*zoom:1}.fuelux .nav-tabs:before,.fuelux .nav-pills:before,.fuelux .nav-tabs:after,.fuelux .nav-pills:after{display:table;line-height:0;content:""}.fuelux .nav-tabs:after,.fuelux .nav-pills:after{clear:both}.fuelux .nav-tabs>li,.fuelux .nav-pills>li{float:left}.fuelux .nav-tabs>li>a,.fuelux .nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.fuelux .nav-tabs{border-bottom:1px solid #ddd}.fuelux .nav-tabs>li{margin-bottom:-1px}.fuelux .nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.fuelux .nav-tabs>li>a:hover,.fuelux .nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.fuelux .nav-tabs>.active>a,.fuelux .nav-tabs>.active>a:hover,.fuelux .nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.fuelux .nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.fuelux .nav-pills>.active>a,.fuelux .nav-pills>.active>a:hover,.fuelux .nav-pills>.active>a:focus{color:#fff;background-color:#08c}.fuelux .nav-stacked>li{float:none}.fuelux .nav-stacked>li>a{margin-right:0}.fuelux .nav-tabs.nav-stacked{border-bottom:0}.fuelux .nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.fuelux .nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.fuelux .nav-tabs.nav-stacked>li>a:hover,.fuelux .nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.fuelux .nav-pills.nav-stacked>li>a{margin-bottom:3px}.fuelux .nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.fuelux .nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.fuelux .nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.fuelux .nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.fuelux .nav .dropdown-toggle:hover .caret,.fuelux .nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.fuelux .nav-tabs .dropdown-toggle .caret{margin-top:8px}.fuelux .nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.fuelux .nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.fuelux .nav>.dropdown.active>a:hover,.fuelux .nav>.dropdown.active>a:focus{cursor:pointer}.fuelux .nav-tabs .open .dropdown-toggle,.fuelux .nav-pills .open .dropdown-toggle,.fuelux .nav>li.dropdown.open.active>a:hover,.fuelux .nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.fuelux .nav li.dropdown.open .caret,.fuelux .nav li.dropdown.open.active .caret,.fuelux .nav li.dropdown.open a:hover .caret,.fuelux .nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.fuelux .tabs-stacked .open>a:hover,.fuelux .tabs-stacked .open>a:focus{border-color:#999}.fuelux .tabbable{*zoom:1}.fuelux .tabbable:before,.fuelux .tabbable:after{display:table;line-height:0;content:""}.fuelux .tabbable:after{clear:both}.fuelux .tab-content{overflow:auto}.fuelux .tabs-below>.nav-tabs,.fuelux .tabs-right>.nav-tabs,.fuelux .tabs-left>.nav-tabs{border-bottom:0}.fuelux .tab-content>.tab-pane,.fuelux .pill-content>.pill-pane{display:none}.fuelux .tab-content>.active,.fuelux .pill-content>.active{display:block}.fuelux .tabs-below>.nav-tabs{border-top:1px solid #ddd}.fuelux .tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.fuelux .tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.fuelux .tabs-below>.nav-tabs>li>a:hover,.fuelux .tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.fuelux .tabs-below>.nav-tabs>.active>a,.fuelux .tabs-below>.nav-tabs>.active>a:hover,.fuelux .tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.fuelux .tabs-left>.nav-tabs>li,.fuelux .tabs-right>.nav-tabs>li{float:none}.fuelux .tabs-left>.nav-tabs>li>a,.fuelux .tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.fuelux .tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.fuelux .tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.fuelux .tabs-left>.nav-tabs>li>a:hover,.fuelux .tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.fuelux .tabs-left>.nav-tabs .active>a,.fuelux .tabs-left>.nav-tabs .active>a:hover,.fuelux .tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.fuelux .tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.fuelux .tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.fuelux .tabs-right>.nav-tabs>li>a:hover,.fuelux .tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.fuelux .tabs-right>.nav-tabs .active>a,.fuelux .tabs-right>.nav-tabs .active>a:hover,.fuelux .tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.fuelux .nav>.disabled>a{color:#999}.fuelux .nav>.disabled>a:hover,.fuelux .nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.fuelux .navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.fuelux .navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.fuelux .navbar-inner:before,.fuelux .navbar-inner:after{display:table;line-height:0;content:""}.fuelux .navbar-inner:after{clear:both}.fuelux .navbar .container{width:auto}.fuelux .nav-collapse.collapse{height:auto;overflow:visible}.fuelux .navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.fuelux .navbar .brand:hover,.fuelux .navbar .brand:focus{text-decoration:none}.fuelux .navbar-text{margin-bottom:0;line-height:40px;color:#777}.fuelux .navbar-link{color:#777}.fuelux .navbar-link:hover,.fuelux .navbar-link:focus{color:#333}.fuelux .navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.fuelux .navbar .btn,.fuelux .navbar .btn-group{margin-top:5px}.fuelux .navbar .btn-group .btn,.fuelux .navbar .input-prepend .btn,.fuelux .navbar .input-append .btn,.fuelux .navbar .input-prepend .btn-group,.fuelux .navbar .input-append .btn-group{margin-top:0}.fuelux .navbar-form{margin-bottom:0;*zoom:1}.fuelux .navbar-form:before,.fuelux .navbar-form:after{display:table;line-height:0;content:""}.fuelux .navbar-form:after{clear:both}.fuelux .navbar-form input,.fuelux .navbar-form select,.fuelux .navbar-form .radio,.fuelux .navbar-form .checkbox{margin-top:5px}.fuelux .navbar-form input,.fuelux .navbar-form select,.fuelux .navbar-form .btn{display:inline-block;margin-bottom:0}.fuelux .navbar-form input[type="image"],.fuelux .navbar-form input[type="checkbox"],.fuelux .navbar-form input[type="radio"]{margin-top:3px}.fuelux .navbar-form .input-append,.fuelux .navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.fuelux .navbar-form .input-append input,.fuelux .navbar-form .input-prepend input{margin-top:0}.fuelux .navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.fuelux .navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.fuelux .navbar-static-top{position:static;margin-bottom:0}.fuelux .navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .navbar-fixed-top,.fuelux .navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.fuelux .navbar-fixed-top .navbar-inner,.fuelux .navbar-static-top .navbar-inner{border-width:0 0 1px}.fuelux .navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.fuelux .navbar-fixed-top .navbar-inner,.fuelux .navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .navbar-static-top .container,.fuelux .navbar-fixed-top .container,.fuelux .navbar-fixed-bottom .container{width:940px}.fuelux .navbar-fixed-top{top:0}.fuelux .navbar-fixed-top .navbar-inner,.fuelux .navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.fuelux .navbar-fixed-bottom{bottom:0}.fuelux .navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.fuelux .navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.fuelux .navbar .nav.pull-right{float:right;margin-right:0}.fuelux .navbar .nav>li{float:left}.fuelux .navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.fuelux .navbar .nav .dropdown-toggle .caret{margin-top:8px}.fuelux .navbar .nav>li>a:focus,.fuelux .navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.fuelux .navbar .nav>.active>a,.fuelux .navbar .nav>.active>a:hover,.fuelux .navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.fuelux .navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.fuelux .navbar .btn-navbar:hover,.fuelux .navbar .btn-navbar:focus,.fuelux .navbar .btn-navbar:active,.fuelux .navbar .btn-navbar.active,.fuelux .navbar .btn-navbar.disabled,.fuelux .navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.fuelux .navbar .btn-navbar:active,.fuelux .navbar .btn-navbar.active{background-color:#ccc \9}.fuelux .navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.fuelux .btn-navbar .icon-bar+.icon-bar{margin-top:3px}.fuelux .navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.fuelux .navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.fuelux .navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.fuelux .navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.fuelux .navbar .nav li.dropdown>a:hover .caret,.fuelux .navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.fuelux .navbar .nav li.dropdown.open>.dropdown-toggle,.fuelux .navbar .nav li.dropdown.active>.dropdown-toggle,.fuelux .navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.fuelux .navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.fuelux .navbar .nav li.dropdown.open>.dropdown-toggle .caret,.fuelux .navbar .nav li.dropdown.active>.dropdown-toggle .caret,.fuelux .navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.fuelux .navbar .pull-right>li>.dropdown-menu,.fuelux .navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.fuelux .navbar .pull-right>li>.dropdown-menu:before,.fuelux .navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.fuelux .navbar .pull-right>li>.dropdown-menu:after,.fuelux .navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.fuelux .navbar .pull-right>li>.dropdown-menu .dropdown-menu,.fuelux .navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.fuelux .navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.fuelux .navbar-inverse .brand,.fuelux .navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.fuelux .navbar-inverse .brand:hover,.fuelux .navbar-inverse .nav>li>a:hover,.fuelux .navbar-inverse .brand:focus,.fuelux .navbar-inverse .nav>li>a:focus{color:#fff}.fuelux .navbar-inverse .brand{color:#999}.fuelux .navbar-inverse .navbar-text{color:#999}.fuelux .navbar-inverse .nav>li>a:focus,.fuelux .navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.fuelux .navbar-inverse .nav .active>a,.fuelux .navbar-inverse .nav .active>a:hover,.fuelux .navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.fuelux .navbar-inverse .navbar-link{color:#999}.fuelux .navbar-inverse .navbar-link:hover,.fuelux .navbar-inverse .navbar-link:focus{color:#fff}.fuelux .navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.fuelux .navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.fuelux .navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.fuelux .navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.fuelux .navbar-inverse .nav li.dropdown>a:hover .caret,.fuelux .navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.fuelux .navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.fuelux .navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.fuelux .navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.fuelux .navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.fuelux .navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.fuelux .navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.fuelux .navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.fuelux .navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.fuelux .navbar-inverse .navbar-search .search-query:focus,.fuelux .navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.fuelux .navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-image:-moz-linear-gradient(top,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}.fuelux .navbar-inverse .btn-navbar:hover,.fuelux .navbar-inverse .btn-navbar:focus,.fuelux .navbar-inverse .btn-navbar:active,.fuelux .navbar-inverse .btn-navbar.active,.fuelux .navbar-inverse .btn-navbar.disabled,.fuelux .navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.fuelux .navbar-inverse .btn-navbar:active,.fuelux .navbar-inverse .btn-navbar.active{background-color:#000 \9}.fuelux .breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux .breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.fuelux .breadcrumb>li>.divider{padding:0 5px;color:#ccc}.fuelux .breadcrumb>.active{color:#999}.fuelux .pagination{margin:20px 0}.fuelux .pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.fuelux .pagination ul>li{display:inline}.fuelux .pagination ul>li>a,.fuelux .pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.fuelux .pagination ul>li>a:hover,.fuelux .pagination ul>li>a:focus,.fuelux .pagination ul>.active>a,.fuelux .pagination ul>.active>span{background-color:#f5f5f5}.fuelux .pagination ul>.active>a,.fuelux .pagination ul>.active>span{color:#999;cursor:default}.fuelux .pagination ul>.disabled>span,.fuelux .pagination ul>.disabled>a,.fuelux .pagination ul>.disabled>a:hover,.fuelux .pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.fuelux .pagination ul>li:first-child>a,.fuelux .pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.fuelux .pagination ul>li:last-child>a,.fuelux .pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.fuelux .pagination-centered{text-align:center}.fuelux .pagination-right{text-align:right}.fuelux .pagination-large ul>li>a,.fuelux .pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.fuelux .pagination-large ul>li:first-child>a,.fuelux .pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.fuelux .pagination-large ul>li:last-child>a,.fuelux .pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.fuelux .pagination-mini ul>li:first-child>a,.fuelux .pagination-small ul>li:first-child>a,.fuelux .pagination-mini ul>li:first-child>span,.fuelux .pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.fuelux .pagination-mini ul>li:last-child>a,.fuelux .pagination-small ul>li:last-child>a,.fuelux .pagination-mini ul>li:last-child>span,.fuelux .pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.fuelux .pagination-small ul>li>a,.fuelux .pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.fuelux .pagination-mini ul>li>a,.fuelux .pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.fuelux .pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.fuelux .pager:before,.fuelux .pager:after{display:table;line-height:0;content:""}.fuelux .pager:after{clear:both}.fuelux .pager li{display:inline}.fuelux .pager li>a,.fuelux .pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.fuelux .pager li>a:hover,.fuelux .pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.fuelux .pager .next>a,.fuelux .pager .next>span{float:right}.fuelux .pager .previous>a,.fuelux .pager .previous>span{float:left}.fuelux .pager .disabled>a,.fuelux .pager .disabled>a:hover,.fuelux .pager .disabled>a:focus,.fuelux .pager .disabled>span{color:#999;cursor:default;background-color:#fff}.fuelux .modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.fuelux .modal-backdrop.fade{opacity:0}.fuelux .modal-backdrop,.fuelux .modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.fuelux .modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.fuelux .modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.fuelux .modal.fade.in{top:10%}.fuelux .modal-header{padding:9px 15px;border-bottom:1px solid #eee}.fuelux .modal-header .close{margin-top:2px}.fuelux .modal-header h3{margin:0;line-height:30px}.fuelux .modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.fuelux .modal-form{margin-bottom:0}.fuelux .modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.fuelux .modal-footer:before,.fuelux .modal-footer:after{display:table;line-height:0;content:""}.fuelux .modal-footer:after{clear:both}.fuelux .modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.fuelux .modal-footer .btn-group .btn+.btn{margin-left:-1px}.fuelux .modal-footer .btn-block+.btn-block{margin-left:0}.fuelux .tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.fuelux .tooltip.in{opacity:.8;filter:alpha(opacity=80)}.fuelux .tooltip.top{padding:5px 0;margin-top:-3px}.fuelux .tooltip.right{padding:0 5px;margin-left:3px}.fuelux .tooltip.bottom{padding:5px 0;margin-top:3px}.fuelux .tooltip.left{padding:0 5px;margin-left:-3px}.fuelux .tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.fuelux .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.fuelux .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.fuelux .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.fuelux .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.fuelux .popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.fuelux .popover.top{margin-top:-10px}.fuelux .popover.right{margin-left:10px}.fuelux .popover.bottom{margin-top:10px}.fuelux .popover.left{margin-left:-10px}.fuelux .popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.fuelux .popover-title:empty{display:none}.fuelux .popover-content{padding:9px 14px}.fuelux .popover .arrow,.fuelux .popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.fuelux .popover .arrow{border-width:11px}.fuelux .popover .arrow:after{border-width:10px;content:""}.fuelux .popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.fuelux .popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.fuelux .popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.fuelux .popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.fuelux .popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.fuelux .popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.fuelux .popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.fuelux .popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.fuelux .thumbnails{margin-left:-20px;list-style:none;*zoom:1}.fuelux .thumbnails:before,.fuelux .thumbnails:after{display:table;line-height:0;content:""}.fuelux .thumbnails:after{clear:both}.fuelux .row-fluid .thumbnails{margin-left:0}.fuelux .thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.fuelux .thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.fuelux a.thumbnail:hover,.fuelux a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.fuelux .thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.fuelux .thumbnail .caption{padding:9px;color:#555}.fuelux .media,.fuelux .media-body{overflow:hidden;*overflow:visible;zoom:1}.fuelux .media,.fuelux .media .media{margin-top:15px}.fuelux .media:first-child{margin-top:0}.fuelux .media-object{display:block}.fuelux .media-heading{margin:0 0 5px}.fuelux .media>.pull-left{margin-right:10px}.fuelux .media>.pull-right{margin-left:10px}.fuelux .media-list{margin-left:0;list-style:none}.fuelux .label,.fuelux .badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.fuelux .label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fuelux .badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.fuelux .label:empty,.fuelux .badge:empty{display:none}.fuelux a.label:hover,.fuelux a.label:focus,.fuelux a.badge:hover,.fuelux a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.fuelux .label-important,.fuelux .badge-important{background-color:#b94a48}.fuelux .label-important[href],.fuelux .badge-important[href]{background-color:#953b39}.fuelux .label-warning,.fuelux .badge-warning{background-color:#f89406}.fuelux .label-warning[href],.fuelux .badge-warning[href]{background-color:#c67605}.fuelux .label-success,.fuelux .badge-success{background-color:#468847}.fuelux .label-success[href],.fuelux .badge-success[href]{background-color:#356635}.fuelux .label-info,.fuelux .badge-info{background-color:#3a87ad}.fuelux .label-info[href],.fuelux .badge-info[href]{background-color:#2d6987}.fuelux .label-inverse,.fuelux .badge-inverse{background-color:#333}.fuelux .label-inverse[href],.fuelux .badge-inverse[href]{background-color:#1a1a1a}.fuelux .btn .label,.fuelux .btn .badge{position:relative;top:-1px}.fuelux .btn-mini .label,.fuelux .btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.fuelux .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.fuelux .progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.fuelux .progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.fuelux .progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.fuelux .progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.fuelux .progress-danger .bar,.fuelux .progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.fuelux .progress-danger.progress-striped .bar,.fuelux .progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.fuelux .progress-success .bar,.fuelux .progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.fuelux .progress-success.progress-striped .bar,.fuelux .progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.fuelux .progress-info .bar,.fuelux .progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.fuelux .progress-info.progress-striped .bar,.fuelux .progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.fuelux .progress-warning .bar,.fuelux .progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.fuelux .progress-warning.progress-striped .bar,.fuelux .progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.fuelux .accordion{margin-bottom:20px}.fuelux .accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.fuelux .accordion-heading{border-bottom:0}.fuelux .accordion-heading .accordion-toggle{display:block;padding:8px 15px}.fuelux .accordion-toggle{cursor:pointer}.fuelux .accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.fuelux .carousel{position:relative;margin-bottom:20px;line-height:1}.fuelux .carousel-inner{position:relative;width:100%;overflow:hidden}.fuelux .carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.fuelux .carousel-inner>.item>img,.fuelux .carousel-inner>.item>a>img{display:block;line-height:1}.fuelux .carousel-inner>.active,.fuelux .carousel-inner>.next,.fuelux .carousel-inner>.prev{display:block}.fuelux .carousel-inner>.active{left:0}.fuelux .carousel-inner>.next,.fuelux .carousel-inner>.prev{position:absolute;top:0;width:100%}.fuelux .carousel-inner>.next{left:100%}.fuelux .carousel-inner>.prev{left:-100%}.fuelux .carousel-inner>.next.left,.fuelux .carousel-inner>.prev.right{left:0}.fuelux .carousel-inner>.active.left{left:-100%}.fuelux .carousel-inner>.active.right{left:100%}.fuelux .carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.fuelux .carousel-control.right{right:15px;left:auto}.fuelux .carousel-control:hover,.fuelux .carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.fuelux .carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.fuelux .carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.fuelux .carousel-indicators .active{background-color:#fff}.fuelux .carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.fuelux .carousel-caption h4,.fuelux .carousel-caption p{line-height:20px;color:#fff}.fuelux .carousel-caption h4{margin:0 0 5px}.fuelux .carousel-caption p{margin-bottom:0}.fuelux .hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.fuelux .hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.fuelux .hero-unit li{line-height:30px}.fuelux .pull-right{float:right}.fuelux .pull-left{float:left}.fuelux .hide{display:none}.fuelux .show{display:block}.fuelux .invisible{visibility:hidden}.fuelux .affix{position:fixed}.fuelux .form-inline .checkbox-custom{padding-left:20px}.fuelux .form-inline .checkbox-custom .checkbox{padding-left:16px}.fuelux .checkbox-custom input[type=checkbox]{position:relative;top:-99999px}.fuelux .checkbox-custom i{width:16px;height:16px;padding-left:16px;margin-right:4px;margin-left:-20px;background-image:url(../img/form.png);background-position:0 1px;background-repeat:no-repeat}.fuelux .checkbox-custom i.checked{background-position:-48px 1px}.fuelux .checkbox-custom i.disabled{background-position:-64px 1px}.fuelux .checkbox-custom i.disabled.checked{background-position:-80px 1px}.fuelux .checkbox-custom:hover i{background-position:-16px 1px}.fuelux .checkbox-custom:hover i.checked{background-position:-32px 1px}.fuelux .checkbox-custom:hover i.disabled{background-position:-64px 1px}.fuelux .checkbox-custom:hover i.disabled.checked{background-position:-80px 1px}.fuelux .combobox{display:inline-block}.fuelux .combobox a{font-size:14px}.fuelux .combobox button.btn{border-radius:0 4px 4px 0}.fuelux .datagrid thead{background-color:#f9f9f9}.fuelux .datagrid thead .datagrid-header-title{float:left;margin-right:10px;font-size:14px;font-weight:normal;line-height:28px}.fuelux .datagrid thead .datagrid-header-left{float:left}.fuelux .datagrid thead .datagrid-header-right{float:right}.fuelux .datagrid thead .datagrid-header-right .search,.fuelux .datagrid thead .datagrid-header-left .search,.fuelux .datagrid thead .datagrid-header-right .filter,.fuelux .datagrid thead .datagrid-header-left .filter{margin-bottom:0;margin-left:8px}.fuelux .datagrid thead .datagrid-header-right .search .dropdown-menu,.fuelux .datagrid thead .datagrid-header-left .search .dropdown-menu,.fuelux .datagrid thead .datagrid-header-right .filter .dropdown-menu,.fuelux .datagrid thead .datagrid-header-left .filter .dropdown-menu{top:auto;left:auto}.fuelux .datagrid thead .sorted{padding-right:30px;color:#333;text-shadow:'none';background-color:#f1f1f1;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f9f9f9),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:-o-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:-moz-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:linear-gradient(to bottom,#f9f9f9,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bebebe;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#ffe5e5e5',GradientType=0)}.fuelux .datagrid thead .sorted i{float:right;margin-top:2px;margin-right:-22px}.fuelux .datagrid thead .sortable{cursor:pointer}.fuelux .datagrid thead .sortable:hover{color:#333;text-shadow:'none';background-color:#f1f1f1;background-image:-moz-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f9f9f9),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:-o-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:linear-gradient(to bottom,#f9f9f9,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bebebe;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#ffe5e5e5',GradientType=0)}.fuelux .datagrid tfoot{background-color:#f9f9f9}.fuelux .datagrid tfoot .datagrid-footer-left{float:left}.fuelux .datagrid tfoot .datagrid-footer-left .grid-controls{margin-top:7px}.fuelux .datagrid tfoot .datagrid-footer-left .grid-controls select{width:60px;margin:0 5px 1px}.fuelux .datagrid tfoot .datagrid-footer-left .grid-controls .grid-pagesize{display:inline-block;margin-bottom:5px;vertical-align:middle}.fuelux .datagrid tfoot .datagrid-footer-left .grid-controls .grid-pagesize .dropdown-menu{top:auto;left:auto}.fuelux .datagrid tfoot .datagrid-footer-left .grid-controls span{font-weight:normal}.fuelux .datagrid tfoot .datagrid-footer-right{float:right}.fuelux .datagrid tfoot .datagrid-footer-right .grid-pager>span{position:relative;top:8px;font-weight:normal}.fuelux .datagrid tfoot .datagrid-footer-right .grid-pager .dropdown-menu{min-width:50px}.fuelux .datagrid tfoot .datagrid-footer-right .grid-pager .combobox{position:relative;top:-2px;display:inline-block;margin-bottom:4px;vertical-align:baseline}.fuelux .datagrid tfoot .datagrid-footer-right .grid-pager>button{position:relative;top:7px}.fuelux .datagrid-stretch-header{margin-bottom:0;border-bottom:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.fuelux .datagrid-stretch-header thead:last-child tr:last-child>th:first-child,.fuelux .datagrid-stretch-header thead:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:0}.fuelux .datagrid-stretch-wrapper{overflow:auto;border:1px solid #ddd}.fuelux .datagrid-stretch-wrapper .datagrid{margin-bottom:0;border:0;border-collapse:collapse;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .datagrid-stretch-wrapper .datagrid td,.fuelux .datagrid-stretch-wrapper .datagrid th{border-bottom:1px solid #ddd}.fuelux .datagrid-stretch-wrapper .datagrid td:first-child,.fuelux .datagrid-stretch-wrapper .datagrid th:first-child{border-left:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fuelux .datagrid-stretch-footer{border-top:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-topright:0;-moz-border-radius-topleft:0}.fuelux .datagrid-stretch-footer th{border-top:0}.fuelux .pillbox{padding:3px}.fuelux .pillbox ul{display:inline-block;margin:0}.fuelux .pillbox li{display:inline-block;float:left;padding:1px 4px 2px;margin:2px;font-size:11.844px;font-weight:bold;line-height:21px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);vertical-align:baseline;cursor:pointer;background-color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fuelux .pillbox li:after{position:relative;top:-2px;float:right;padding-left:4px;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;content:" \00D7";opacity:.2;filter:alpha(opacity=20)}.fuelux .pillbox li:hover:after{opacity:.4;filter:alpha(opacity=40)}.fuelux .pillbox li.status-important{background-color:#b94a48}.fuelux .pillbox li.status-warning{background-color:#f89406}.fuelux .pillbox li.status-success{background-color:#468847}.fuelux .pillbox li.status-info{background-color:#3a87ad}.fuelux .radio-custom input[type=radio]{display:none}.fuelux .radio-custom i{width:16px;height:16px;padding-left:16px;margin-right:4px;margin-left:-20px;background-image:url(../img/form.png);background-position:0 -15px;background-repeat:no-repeat}.fuelux .radio-custom i.checked{background-position:-48px -15px}.fuelux .radio-custom i.disabled{background-position:-64px -15px}.fuelux .radio-custom i.disabled.checked{background-position:-80px -15px}.fuelux .radio-custom:hover i{background-position:-16px -15px}.fuelux .radio-custom:hover i.checked{background-position:-32px -15px}.fuelux .radio-custom:hover i.disabled{background-position:-64px -15px}.fuelux .radio-custom:hover i.disabled.checked{background-position:-80px -15px}.fuelux .spinner input{float:left;width:43px}.fuelux .spinner .btn{position:relative;width:20px;height:14px;padding-top:0;padding-right:9px;padding-left:9px}.fuelux .spinner .btn.disabled{cursor:not-allowed}.fuelux .spinner .spinner-buttons{position:relative;left:-22px;float:left;width:20px;height:28px}.fuelux .spinner .spinner-up{top:2px;padding:0 0 4px 1px}.fuelux .spinner .spinner-up i{position:relative;top:-4px}.fuelux .spinner .spinner-down{top:2px;height:13px;padding:0 0 4px 1px}.fuelux .spinner .spinner-down i{position:relative;top:-5px}.fuelux .search{display:inline-block}.fuelux .select .dropdown-label{display:inline-block;padding:0 10px 0 0;margin:0;font-weight:normal;color:#333;text-align:left}.fuelux #selectTextSize{position:absolute;top:0;display:inline-block;visibility:hidden}.fuelux .tree{position:relative;padding:10px 15px 0 15px;overflow-x:hidden;overflow-y:auto;border:1px solid #bbb;border-radius:4px 4px 4px 4px}.fuelux .tree .tree-folder{width:100%;min-height:20px;margin-top:1px;cursor:pointer}.fuelux .tree .tree-folder .tree-folder-header{position:relative;height:20px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.fuelux .tree .tree-folder .tree-folder-header:hover{background-color:#dfeef5}.fuelux .tree .tree-folder .tree-folder-header i{position:absolute;top:1px;left:5px;float:left}.fuelux .tree .tree-folder .tree-folder-header .tree-folder-name{padding-left:29px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fuelux .tree .tree-folder .tree-folder-content{margin-left:23px}.fuelux .tree .tree-item{position:relative;width:100%;height:20px;margin-top:1px;cursor:pointer;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.fuelux .tree .tree-item:hover{background-color:#dfeef5}.fuelux .tree .tree-item .tree-item-name{position:absolute;left:29px}.fuelux .tree .tree-item .tree-dot{position:absolute;top:8px;left:10px;display:block;width:4px;height:4px;background-color:#333;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.fuelux .tree .tree-item .icon-ok{position:absolute;top:1px;left:5px}.fuelux .tree .tree-selected{background-color:#b9dff1}.fuelux .tree .tree-selected:hover{background-color:#b9dff1}.fuelux .wizard{background-color:#f9f9f9;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.fuelux .wizard:before,.fuelux .wizard:after{display:table;line-height:0;content:""}.fuelux .wizard:after{clear:both}.fuelux .wizard ul{padding:0;margin:0;list-style:none outside none}.fuelux .wizard ul li{position:relative;float:left;height:46px;padding:0 20px 0 30px;margin:0;font-size:16px;line-height:46px;color:#999;cursor:default;background:#ededed}.fuelux .wizard ul li .chevron{position:absolute;top:0;right:-14px;display:block;border:24px solid transparent;border-right:0;border-left:14px solid #d4d4d4}.fuelux .wizard ul li .chevron:before{position:absolute;top:-24px;right:1px;display:block;border:24px solid transparent;border-right:0;border-left:14px solid #ededed;content:""}.fuelux .wizard ul li.complete{color:#468847;background:#f3f4f5}.fuelux .wizard ul li.complete:hover{cursor:pointer;background:#e7eff8}.fuelux .wizard ul li.complete:hover .chevron:before{border-left:14px solid #e7eff8}.fuelux .wizard ul li.complete .chevron:before{border-left:14px solid #f3f4f5}.fuelux .wizard ul li.active{color:#3a87ad;background:#f1f6fc}.fuelux .wizard ul li.active .chevron:before{border-left:14px solid #f1f6fc}.fuelux .wizard ul li .badge{margin-right:8px}.fuelux .wizard ul li:nth-child(1){z-index:10;padding-left:20px;border-radius:4px 0 0 4px}.fuelux .wizard ul li:nth-child(2){z-index:9}.fuelux .wizard ul li:nth-child(3){z-index:8}.fuelux .wizard ul li:nth-child(4){z-index:7}.fuelux .wizard ul li:nth-child(5){z-index:6}.fuelux .wizard ul li:nth-child(6){z-index:5}.fuelux .wizard ul li:nth-child(7){z-index:4}.fuelux .wizard ul li:nth-child(8){z-index:3}.fuelux .wizard ul li:nth-child(9){z-index:2}.fuelux .wizard ul li:nth-child(10){z-index:1}.fuelux .wizard .actions{float:right;padding-right:15px;line-height:44px;vertical-align:middle}.fuelux .wizard .actions a{margin-right:8px;font-size:12px;line-height:45px}.fuelux .wizard .actions .btn-prev i{margin-right:5px}.fuelux .wizard .actions .btn-next i{margin-left:5px}.fuelux .step-content .step-pane{display:none}.fuelux .step-content .active{display:block}.fuelux .step-content .active .btn-group .active{display:inline-block}
\ No newline at end of file
diff --git a/opendaylight/web/root/src/main/resources/css/opendaylight.css b/opendaylight/web/root/src/main/resources/css/opendaylight.css
new file mode 100644 (file)
index 0000000..9a988b0
--- /dev/null
@@ -0,0 +1,80 @@
+.fuelux [class^="icon-"],
+.fuelux [class*=" icon-"] {
+  display: inline-block;
+  width: 14px;
+  height: 14px;
+  margin-top: 1px;
+  *margin-right: .3em;
+  line-height: 14px;
+  vertical-align: text-top;
+  background-position: 14px 14px;
+  background-repeat: no-repeat;
+}
+
+.fuelux .icon-white,
+.fuelux .nav-pills > .active > a > [class^="icon-"],
+.fuelux .nav-pills > .active > a > [class*=" icon-"],
+.fuelux .nav-list > .active > a > [class^="icon-"],
+.fuelux .nav-list > .active > a > [class*=" icon-"],
+.fuelux .navbar-inverse .nav > .active > a > [class^="icon-"],
+.fuelux .navbar-inverse .nav > .active > a > [class*=" icon-"],
+.fuelux .dropdown-menu > li > a:hover > [class^="icon-"],
+.fuelux .dropdown-menu > li > a:focus > [class^="icon-"],
+.fuelux .dropdown-menu > li > a:hover > [class*=" icon-"],
+.fuelux .dropdown-menu > li > a:focus > [class*=" icon-"],
+.fuelux .dropdown-menu > .active > a > [class^="icon-"],
+.fuelux .dropdown-menu > .active > a > [class*=" icon-"],
+.fuelux .dropdown-submenu:hover > a > [class^="icon-"],
+.fuelux .dropdown-submenu:focus > a > [class^="icon-"],
+.fuelux .dropdown-submenu:hover > a > [class*=" icon-"],
+.fuelux .dropdown-submenu:focus > a > [class*=" icon-"] {
+}
+
+.fuelux .icon-search {
+  background:url('../img/search.png') 0 0 no-repeat;
+  height: 16px;
+  line-height: 16px;
+  width: 16px;
+}
+.fuelux .icon-remove {
+  background:url('../img/searchremove.png') 0 0 no-repeat;
+  height: 16px;
+  line-height: 16px;
+  width: 16px;
+}
+
+.fuelux .icon-chevron-up {
+  background:url('../img/sort_up.png') 0 0 no-repeat;
+  height: 16px;
+  line-height: 16px;
+  width: 16px;
+}
+
+.fuelux .icon-chevron-down {
+  background:url('../img/sort_down.png') 0 0 no-repeat;
+  height: 16px;
+  line-height: 16px;
+  width: 16px;
+}
+
+.fuelux .icon-chevron-left {
+  background:url('../img/nextpageleft.png') 0 0 no-repeat;
+  height: 16px;
+  line-height: 16px;
+  width: 16px;
+}
+
+.fuelux .icon-chevron-right {
+  background:url('../img/nextpageright.png') 0 0 no-repeat;
+  height: 16px;
+  line-height: 16px;
+  width: 16px;
+}
+
+.fuelux .icon-chevron-right {
+  background:url('../img/nextpageright.png') 0 0 no-repeat;
+  height: 16px;
+  line-height: 16px;
+  width: 16px;
+}
+
diff --git a/opendaylight/web/root/src/main/resources/img/form.png b/opendaylight/web/root/src/main/resources/img/form.png
new file mode 100755 (executable)
index 0000000..ce846da
Binary files /dev/null and b/opendaylight/web/root/src/main/resources/img/form.png differ
diff --git a/opendaylight/web/root/src/main/resources/img/nextpageleft.png b/opendaylight/web/root/src/main/resources/img/nextpageleft.png
new file mode 100644 (file)
index 0000000..62126b1
Binary files /dev/null and b/opendaylight/web/root/src/main/resources/img/nextpageleft.png differ
diff --git a/opendaylight/web/root/src/main/resources/img/nextpageright.png b/opendaylight/web/root/src/main/resources/img/nextpageright.png
new file mode 100644 (file)
index 0000000..2a71a14
Binary files /dev/null and b/opendaylight/web/root/src/main/resources/img/nextpageright.png differ
diff --git a/opendaylight/web/root/src/main/resources/img/search.png b/opendaylight/web/root/src/main/resources/img/search.png
new file mode 100644 (file)
index 0000000..b8742d2
Binary files /dev/null and b/opendaylight/web/root/src/main/resources/img/search.png differ
diff --git a/opendaylight/web/root/src/main/resources/img/searchremove.png b/opendaylight/web/root/src/main/resources/img/searchremove.png
new file mode 100644 (file)
index 0000000..3809f51
Binary files /dev/null and b/opendaylight/web/root/src/main/resources/img/searchremove.png differ
diff --git a/opendaylight/web/root/src/main/resources/img/sort_down.png b/opendaylight/web/root/src/main/resources/img/sort_down.png
new file mode 100644 (file)
index 0000000..708e44e
Binary files /dev/null and b/opendaylight/web/root/src/main/resources/img/sort_down.png differ
diff --git a/opendaylight/web/root/src/main/resources/img/sort_up.png b/opendaylight/web/root/src/main/resources/img/sort_up.png
new file mode 100644 (file)
index 0000000..0b5c041
Binary files /dev/null and b/opendaylight/web/root/src/main/resources/img/sort_up.png differ
diff --git a/opendaylight/web/root/src/main/resources/js/datasource.js b/opendaylight/web/root/src/main/resources/js/datasource.js
new file mode 100755 (executable)
index 0000000..8226df0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Fuel UX Data components - static data source
+ * https://github.com/ExactTarget/fuelux-data
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+(function (root, factory) {
+       if (typeof define === 'function' && define.amd) {
+               define(['underscore'], factory);
+       } else {
+               root.StaticDataSource = factory();
+       }
+}(this, function () {
+
+       var StaticDataSource = function (options) {
+               this._formatter = options.formatter;
+               this._columns = options.columns;
+               this._delay = options.delay || 0;
+               this._data = options.data;
+       };
+
+       StaticDataSource.prototype = {
+
+               columns: function () {
+                       return this._columns;
+               },
+
+               data: function (options, callback) {
+                       var self = this;
+
+                       setTimeout(function () {
+                               var data = $.extend(true, [], self._data);
+
+                               // SEARCHING
+                               if (options.search) {
+                                       data = _.filter(data, function (item) {
+                                               var match = false;
+
+                                               _.each(item, function (prop) {
+                                                       if (_.isString(prop) || _.isFinite(prop)) {
+                                                               if (prop.toString().toLowerCase().indexOf(options.search.toLowerCase()) !== -1) match = true;
+                                                       }
+                                               });
+
+                                               return match;
+                                       });
+                               }
+
+                               // FILTERING
+                               if (options.filter) {
+                                       data = _.filter(data, function (item) {
+                                               switch(options.filter.value) {
+                                                       case 'lt5m':
+                                                               if(item.population < 5000000) return true;
+                                                               break;
+                                                       case 'gte5m':
+                                                               if(item.population >= 5000000) return true;
+                                                               break;
+                                                       default:
+                                                               return true;
+                                                               break;
+                                               }
+                                       });
+                               }
+
+                               var count = data.length;
+
+                               // SORTING
+                               if (options.sortProperty) {
+                                       data = _.sortBy(data, options.sortProperty);
+                                       if (options.sortDirection === 'desc') data.reverse();
+                               }
+
+                               // PAGING
+                               var startIndex = options.pageIndex * options.pageSize;
+                               var endIndex = startIndex + options.pageSize;
+                               var end = (endIndex > count) ? count : endIndex;
+                               var pages = Math.ceil(count / options.pageSize);
+                               var page = options.pageIndex + 1;
+                               var start = startIndex + 1;
+
+                               data = data.slice(startIndex, endIndex);
+
+                               if (self._formatter) self._formatter(data);
+
+                               callback({ data: data, start: start, end: end, count: count, pages: pages, page: page });
+
+                       }, this._delay)
+               }
+       };
+
+       return StaticDataSource;
+}));
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/COPYING b/opendaylight/web/root/src/main/resources/js/fuelux/COPYING
new file mode 100644 (file)
index 0000000..9b8ce79
--- /dev/null
@@ -0,0 +1,33 @@
+Copyright (C) 2012, ExactTarget, Inc.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in the
+Software without restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+====================================================================
+
+The above license does not apply to the following bundled components:
+
+Â¥      jQuery located at lib/jquery.js
+Â¥      Bootstrap Apache 2.0 Located under lib/bootstrap
+Â¥      RequireJS located at lib/require.js
+Â¥      QUnit located under lib/qunit
+Â¥      Grunt located under node-modules/grunt
+Â¥      Grunt-contrib located under node-modules/grunt-contrib
+Â¥      Grunt-recess located under node-modules/grunt-recess
+
+Licensing information regarding the above packages can be found in the THIRD-PARTY file.
\ No newline at end of file
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/all.min.js b/opendaylight/web/root/src/main/resources/js/fuelux/all.min.js
new file mode 100755 (executable)
index 0000000..2f9e721
--- /dev/null
@@ -0,0 +1,4 @@
+/*! Fuel UX - v2.3.1 - 2013-08-02
+* https://github.com/ExactTarget/fuelux
+* Copyright (c) 2013 ExactTarget; Licensed MIT */
+(function(){(function(a){var b;define("bootstrap/bootstrap-transition",["jquery"],function(){return function(){!function(a){a(function(){a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery)}.call(a),b})})(this),function(a){var b;define("bootstrap/bootstrap-affix",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.options=a.extend({},a.fn.affix.defaults,c),this.$window=a(window).on("scroll.affix.data-api",a.proxy(this.checkPosition,this)).on("click.affix.data-api",a.proxy(function(){setTimeout(a.proxy(this.checkPosition,this),1)},this)),this.$element=a(b),this.checkPosition()};b.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var b=a(document).height(),c=this.$window.scrollTop(),d=this.$element.offset(),e=this.options.offset,f=e.bottom,g=e.top,h="affix affix-top affix-bottom",i;typeof e!="object"&&(f=g=e),typeof g=="function"&&(g=e.top()),typeof f=="function"&&(f=e.bottom()),i=this.unpin!=null&&c+this.unpin<=d.top?!1:f!=null&&d.top+this.$element.height()>=b-f?"bottom":g!=null&&c<=g?"top":!1;if(this.affixed===i)return;this.affixed=i,this.unpin=i=="bottom"?d.top-c:null,this.$element.removeClass(h).addClass("affix"+(i?"-"+i:""))};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("affix"),f=typeof c=="object"&&c;e||d.data("affix",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.defaults={offset:0},a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-alert",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed").remove()}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.alert.data-api",b,c.prototype.close)}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-button",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a=a+"Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-carousel",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.prototype={cycle:function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(b){var c=this.getActiveIndex(),d=this;if(b>this.$items.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){d.to(b)}):c==b?this.pause().cycle():this.slide(b>c?"next":"prev",a(this.$items[b]))},pause:function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this,j;this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h](),j=a.Event("slide",{relatedTarget:e[0],direction:g});if(e.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")}));if(a.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(j);if(j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})}else{this.$element.trigger(j);if(j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=a.extend({},a.fn.carousel.defaults,typeof c=="object"&&c),g=typeof c=="string"?c:f.slide;e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.defaults={interval:5e3,pause:"hover"},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),c.data()),g;e.carousel(f),(g=c.attr("data-slide-to"))&&e.data("carousel").pause().to(g).cycle(),b.preventDefault()})}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-collapse",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b,c,d,e;if(this.transitioning||this.$element.hasClass("in"))return;b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find("> .accordion-group > .in");if(d&&d.length){e=d.data("collapse");if(e&&e.transitioning)return;d.collapse("hide"),e||d.data("collapse",null)}this.$element[b](0),this.transition("addClass",a.Event("show"),"shown"),a.support.transition&&this.$element[b](this.$element[0][c])},hide:function(){var b;if(this.transitioning||!this.$element.hasClass("in"))return;b=this.dimension(),this.reset(this.$element[b]()),this.transition("removeClass",a.Event("hide"),"hidden"),this.$element[b](0)},reset:function(a){var b=this.dimension();return this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("collapse"),this},transition:function(b,c,d){var e=this,f=function(){c.type=="show"&&e.reset(),e.transitioning=0,e.$element.trigger(d)};this.$element.trigger(c);if(c.isDefaultPrevented())return;this.transitioning=1,this.$element[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=a.extend({},a.fn.collapse.defaults,d.data(),typeof c=="object"&&c);e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();c[a(e).hasClass("in")?"addClass":"removeClass"]("collapsed"),a(e).collapse(f)})}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-dropdown",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){function d(){a(".dropdown-backdrop").remove(),a(b).each(function(){e(a(this)).removeClass("open")})}function e(b){var c=b.attr("data-target"),d;c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,"")),d=c&&a(c);if(!d||!d.length)d=b.parent();return d}var b="[data-toggle=dropdown]",c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),f,g;if(c.is(".disabled, :disabled"))return;return f=e(c),g=f.hasClass("open"),d(),g||("ontouchstart"in document.documentElement&&a('<div class="dropdown-backdrop"/>').insertBefore(a(this)).on("click",d),f.toggleClass("open")),c.focus(),!1},keydown:function(c){var d,f,g,h,i,j;if(!/(38|40|27)/.test(c.keyCode))return;d=a(this),c.preventDefault(),c.stopPropagation();if(d.is(".disabled, :disabled"))return;h=e(d),i=h.hasClass("open");if(!i||i&&c.keyCode==27)return c.which==27&&h.find(b).focus(),d.click();f=a("[role=menu] li:not(.divider):visible a",h);if(!f.length)return;j=f.index(f.filter(":focus")),c.keyCode==38&&j>0&&j--,c.keyCode==40&&j<f.length-1&&j++,~j||(j=0),f.eq(j).focus()}};var f=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=f,this},a(document).on("click.dropdown.data-api",d).on("click.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.dropdown.data-api",b,c.prototype.toggle).on("keydown.dropdown.data-api",b+", [role=menu]",c.prototype.keydown)}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-modal",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.options=c,this.$element=a(b).delegate('[data-dismiss="modal"]',"click.dismiss.modal",a.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};b.prototype={constructor:b,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var b=this,c=a.Event("show");this.$element.trigger(c);if(this.isShown||c.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var c=a.support.transition&&b.$element.hasClass("fade");b.$element.parent().length||b.$element.appendTo(document.body),b.$element.show(),c&&b.$element[0].offsetWidth,b.$element.addClass("in").attr("aria-hidden",!1),b.enforceFocus(),c?b.$element.one(a.support.transition.end,function(){b.$element.focus().trigger("shown")}):b.$element.focus().trigger("shown")})},hide:function(b){b&&b.preventDefault();var c=this;b=a.Event("hide"),this.$element.trigger(b);if(!this.isShown||b.isDefaultPrevented())return;this.isShown=!1,this.escape(),a(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),a.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var b=this;a(document).on("focusin.modal",function(a){b.$element[0]!==a.target&&!b.$element.has(a.target).length&&b.$element.focus()})},escape:function(){var a=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(b){b.which==27&&a.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),b.hideModal()},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),b.hideModal()})},hideModal:function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?a.proxy(this.$element[0].focus,this.$element[0]):a.proxy(this.hide,this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!b)return;e?this.$backdrop.one(a.support.transition.end,b):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b):b()):b&&b()}};var c=a.fn.modal;a.fn.modal=function(c){return this.each(function(){var d=a(this),e=d.data("modal"),f=a.extend({},a.fn.modal.defaults,d.data(),typeof c=="object"&&c);e||d.data("modal",e=new b(this,f)),typeof c=="string"?e[c]():f.show&&e.show()})},a.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f).one("hide",function(){c.focus()})})}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-tooltip",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(a,b){this.init("tooltip",a,b)};b.prototype={constructor:b,init:function(b,c,d){var e,f,g,h,i;this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.enabled=!0,g=this.options.trigger.split(" ");for(i=g.length;i--;)h=g[i],h=="click"?this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this)):h!="manual"&&(e=h=="hover"?"mouseenter":"focus",f=h=="hover"?"mouseleave":"blur",this.$element.on(e+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(f+"."+this.type,this.options.selector,a.proxy(this.leave,this)));this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(b){return b=a.extend({},a.fn[this.type].defaults,this.$element.data(),b),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},enter:function(b){var c=a.fn[this.type].defaults,d={},e;this._options&&a.each(this._options,function(a,b){c[a]!=b&&(d[a]=b)}),e=a(b.currentTarget)[this.type](d).data(this.type);if(!e.options.delay||!e.options.delay.show)return e.show();clearTimeout(this.timeout),e.hoverState="in",this.timeout=setTimeout(function(){e.hoverState=="in"&&e.show()},e.options.delay.show)},leave:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!c.options.delay||!c.options.delay.hide)return c.hide();c.hoverState="out",this.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},show:function(){var b,c,d,e,f,g,h=a.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(h);if(h.isDefaultPrevented())return;b=this.tip(),this.setContent(),this.options.animation&&b.addClass("fade"),f=typeof this.options.placement=="function"?this.options.placement.call(this,b[0],this.$element[0]):this.options.placement,b.detach().css({top:0,left:0,display:"block"}),this.options.container?b.appendTo(this.options.container):b.insertAfter(this.$element),c=this.getPosition(),d=b[0].offsetWidth,e=b[0].offsetHeight;switch(f){case"bottom":g={top:c.top+c.height,left:c.left+c.width/2-d/2};break;case"top":g={top:c.top-e,left:c.left+c.width/2-d/2};break;case"left":g={top:c.top+c.height/2-e/2,left:c.left-d};break;case"right":g={top:c.top+c.height/2-e/2,left:c.left+c.width}}this.applyPlacement(g,f),this.$element.trigger("shown")}},applyPlacement:function(a,b){var c=this.tip(),d=c[0].offsetWidth,e=c[0].offsetHeight,f,g,h,i;c.offset(a).addClass(b).addClass("in"),f=c[0].offsetWidth,g=c[0].offsetHeight,b=="top"&&g!=e&&(a.top=a.top+e-g,i=!0),b=="bottom"||b=="top"?(h=0,a.left<0&&(h=a.left*-2,a.left=0,c.offset(a),f=c[0].offsetWidth,g=c[0].offsetHeight),this.replaceArrow(h-d+f,f,"left")):this.replaceArrow(g-e,g,"top"),i&&c.offset(a)},replaceArrow:function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},setContent:function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},hide:function(){function e(){var b=setTimeout(function(){c.off(a.support.transition.end).detach()},500);c.one(a.support.transition.end,function(){clearTimeout(b),c.detach()})}var b=this,c=this.tip(),d=a.Event("hide");this.$element.trigger(d);if(d.isDefaultPrevented())return;return c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?e():c.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var b=this.$element[0];return a.extend({},typeof b.getBoundingClientRect=="function"?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},getTitle:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a},tip:function(){return this.$tip=this.$tip||a(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(b){var c=b?a(b.currentTarget)[this.type](this._options).data(this.type):this;c.tip().hasClass("in")?c.hide():c.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("tooltip"),f=typeof c=="object"&&c;e||d.data("tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-popover",["bootstrap/bootstrap-transition","bootstrap/bootstrap-tooltip"],function(){return function(){!function(a){var b=function(a,b){this.init("popover",a,b)};b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype,{constructor:b,setContent:function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var a,b=this.$element,c=this.options;return a=(typeof c.content=="function"?c.content.call(b[0]):c.content)||b.attr("data-content"),a},tip:function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("popover"),f=typeof c=="object"&&c;e||d.data("popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.defaults=a.extend({},a.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-scrollspy",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){function b(b,c){var d=a.proxy(this.process,this),e=a(b).is("body")?a(window):a(b),f;this.options=a.extend({},a.fn.scrollspy.defaults,c),this.$scrollElement=e.on("scroll.scroll-spy.data-api",d),this.selector=(this.options.target||(f=a(b).attr("href"))&&f.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=a("body"),this.refresh(),this.process()}b.prototype={constructor:b,refresh:function(){var b=this,c;this.offsets=a([]),this.targets=a([]),c=this.$body.find(this.selector).map(function(){var c=a(this),d=c.data("target")||c.attr("href"),e=/^#\w/.test(d)&&a(d);return e&&e.length&&[[e.position().top+(!a.isWindow(b.$scrollElement.get(0))&&b.$scrollElement.scrollTop()),d]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},process:function(){var a=this.$scrollElement.scrollTop()+this.options.offset,b=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,c=b-this.$scrollElement.height(),d=this.offsets,e=this.targets,f=this.activeTarget,g;if(a>=c)return f!=(g=e.last()[0])&&this.activate(g);for(g=d.length;g--;)f!=e[g]&&a>=d[g]&&(!d[g+1]||a<=d[g+1])&&this.activate(e[g])},activate:function(b){var c,d;this.activeTarget=b,a(this.selector).parent(".active").removeClass("active"),d=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',c=a(d).parent("li").addClass("active"),c.parent(".dropdown-menu").length&&(c=c.closest("li.dropdown").addClass("active")),c.trigger("activate")}};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("scrollspy"),f=typeof c=="object"&&c;e||d.data("scrollspy",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.defaults={offset:10},a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-tab",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b){this.element=a(b)};b.prototype={constructor:b,show:function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target"),e,f,g;d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;e=c.find(".active:last a")[0],g=a.Event("show",{relatedTarget:e}),b.trigger(g);if(g.isDefaultPrevented())return;f=a(d),this.activate(b.parent("li"),c),this.activate(f,f.parent(),function(){b.trigger({type:"shown",relatedTarget:e})})},activate:function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g):g(),e.removeClass("in")}};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("tab");e||d.data("tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery)}.call(a),b})}(this),function(a){var b;define("bootstrap/bootstrap-typeahead",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.typeahead.defaults,c),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=a(this.options.menu),this.shown=!1,this.listen()};b.prototype={constructor:b,select:function(){var a=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(a)).change(),this.hide()},updater:function(a){return a},show:function(){var b=a.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:b.top+b.height,left:b.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(b){var c;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(c=a.isFunction(this.source)?this.source(this.query,a.proxy(this.process,this)):this.source,c?this.process(c):this)},process:function(b){var c=this;return b=a.grep(b,function(a){return c.matcher(a)}),b=this.sorter(b),b.length?this.render(b.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(a){return~a.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(a){var b=[],c=[],d=[],e;while(e=a.shift())e.toLowerCase().indexOf(this.query.toLowerCase())?~e.indexOf(this.query)?c.push(e):d.push(e):b.push(e);return b.concat(c,d)},highlighter:function(a){var b=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return a.replace(new RegExp("("+b+")","ig"),function(a,b){return"<strong>"+b+"</strong>"})},render:function(b){var c=this;return b=a(b).map(function(b,d){return b=a(c.options.item).attr("data-value",d),b.find("a").html(c.highlighter(d)),b[0]}),b.first().addClass("active"),this.$menu.html(b),this},next:function(b){var c=this.$menu.find(".active").removeClass("active"),d=c.next();d.length||(d=a(this.$menu.find("li")[0])),d.addClass("active")},prev:function(a){var b=this.$menu.find(".active").removeClass("active"),c=b.prev();c.length||(c=this.$menu.find("li").last()),c.addClass("active")},listen:function(){this.$element.on("focus",a.proxy(this.focus,this)).on("blur",a.proxy(this.blur,this)).on("keypress",a.proxy(this.keypress,this)).on("keyup",a.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",a.proxy(this.keydown,this)),this.$menu.on("click",a.proxy(this.click,this)).on("mouseenter","li",a.proxy(this.mouseenter,this)).on("mouseleave","li",a.proxy(this.mouseleave,this))},eventSupported:function(a){var b=a in this.$element;return b||(this.$element.setAttribute(a,"return;"),b=typeof this.$element[a]=="function"),b},move:function(a){if(!this.shown)return;switch(a.keyCode){case 9:case 13:case 27:a.preventDefault();break;case 38:a.preventDefault(),this.prev();break;case 40:a.preventDefault(),this.next()}a.stopPropagation()},keydown:function(b){this.suppressKeyPressRepeat=~a.inArray(b.keyCode,[40,38,9,13,27]),this.move(b)},keypress:function(a){if(this.suppressKeyPressRepeat)return;this.move(a)},keyup:function(a){switch(a.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}a.stopPropagation(),a.preventDefault()},focus:function(a){this.focused=!0},blur:function(a){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(a){a.stopPropagation(),a.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(b){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")},mouseleave:function(a){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var c=a.fn.typeahead;a.fn.typeahead=function(c){return this.each(function(){var d=a(this),e=d.data("typeahead"),f=typeof c=="object"&&c;e||d.data("typeahead",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},a.fn.typeahead.Constructor=b,a.fn.typeahead.noConflict=function(){return a.fn.typeahead=c,this},a(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(b){var c=a(this);if(c.data("typeahead"))return;c.typeahead(c.data())})}(window.jQuery)}.call(a),b})}(this),define("fuelux/checkbox",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.checkbox.defaults,c),this.$label=this.$element.parent(),this.$icon=this.$label.find("i"),this.$chk=this.$label.find("input[type=checkbox]"),this.setState(this.$chk),this.$chk.on("change",b.proxy(this.itemchecked,this))};c.prototype={constructor:c,setState:function(a){var b=a.is(":checked"),c=a.is(":disabled");this.$icon.removeClass("checked").removeClass("disabled"),b===!0&&this.$icon.addClass("checked"),c===!0&&this.$icon.addClass("disabled")},enable:function(){this.$chk.attr("disabled",!1),this.$icon.removeClass("disabled")},disable:function(){this.$chk.attr("disabled",!0),this.$icon.addClass("disabled")},toggle:function(){this.$chk.click()},itemchecked:function(a){var c=b(a.target);this.setState(c)}},b.fn.checkbox=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("checkbox"),h=typeof a=="object"&&a;g||f.data("checkbox",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.checkbox.defaults={},b.fn.checkbox.Constructor=c,b(function(){b(window).on("load",function(){b(".checkbox-custom > input[type=checkbox]").each(function(){var a=b(this);if(a.data("checkbox"))return;a.checkbox(a.data())})})})}),define("fuelux/util",["require","jquery"],function(a){function c(a,c){return(a.textContent||a.innerText||b(a).text()||"").toLowerCase()===(c||"").toLowerCase()}var b=a("jquery");b.expr[":"].fuelTextExactCI=b.expr.createPseudo?b.expr.createPseudo(function(a){return function(b){return c(b,a)}}):function(a,b,d){return c(a,d[3])}}),define("fuelux/combobox",["require","jquery","./util"],function(a){var b=a("jquery");a("./util");var c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.combobox.defaults,c),this.$element.on("click","a",b.proxy(this.itemclicked,this)),this.$element.on("change","input",b.proxy(this.inputchanged,this)),this.$input=this.$element.find("input"),this.$button=this.$element.find(".btn"),this.setDefaultSelection()};c.prototype={constructor:c,selectedItem:function(){var a=this.$selectedItem,c={};if(a){var d=this.$selectedItem.text();c=b.extend({text:d},this.$selectedItem.data())}else c={text:this.$input.val()};return c},selectByText:function(a){var b="li:fuelTextExactCI("+a+")";this.selectBySelector(b)},selectByValue:function(a){var b='li[data-value="'+a+'"]';this.selectBySelector(b)},selectByIndex:function(a){var b="li:eq("+a+")";this.selectBySelector(b)},selectBySelector:function(a){var b=this.$element.find(a);typeof b[0]!="undefined"?(this.$selectedItem=b,this.$input.val(this.$selectedItem.text())):this.$selectedItem=null},setDefaultSelection:function(){var a="li[data-selected=true]:first",b=this.$element.find(a);b.length>0&&(this.selectBySelector(a),b.removeData("selected"),b.removeAttr("data-selected"))},enable:function(){this.$input.removeAttr("disabled"),this.$button.removeClass("disabled")},disable:function(){this.$input.attr("disabled",!0),this.$button.addClass("disabled")},itemclicked:function(a){this.$selectedItem=b(a.target).parent(),this.$input.val(this.$selectedItem.text()).trigger("change",{synthetic:!0});var c=this.selectedItem();this.$element.trigger("changed",c),a.preventDefault()},inputchanged:function(a,c){if(c&&c.synthetic)return;var d=b(a.target).val();this.selectByText(d);var e=this.selectedItem();e.text.length===0&&(e={text:d}),this.$element.trigger("changed",e)}},b.fn.combobox=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("combobox"),h=typeof a=="object"&&a;g||f.data("combobox",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.combobox.defaults={},b.fn.combobox.Constructor=c,b(function(){b(window).on("load",function(){b(".combobox").each(function(){var a=b(this);if(a.data("combobox"))return;a.combobox(a.data())})}),b("body").on("mousedown.combobox.data-api",".combobox",function(a){var c=b(this);if(c.data("combobox"))return;c.combobox(c.data())})})}),define("fuelux/datagrid",["require","jquery"],function(a){var b=a("jquery"),c=22,d=function(a,c){this.$element=b(a),this.$thead=this.$element.find("thead"),this.$tfoot=this.$element.find("tfoot"),this.$footer=this.$element.find("tfoot th"),this.$footerchildren=this.$footer.children().show().css("visibility","hidden"),this.$topheader=this.$element.find("thead th"),this.$searchcontrol=this.$element.find(".datagrid-search"),this.$filtercontrol=this.$element.find(".filter"),this.$pagesize=this.$element.find(".grid-pagesize"),this.$pageinput=this.$element.find(".grid-pager input"),this.$pagedropdown=this.$element.find(".grid-pager .dropdown-menu"),this.$prevpagebtn=this.$element.find(".grid-prevpage"),this.$nextpagebtn=this.$element.find(".grid-nextpage"),this.$pageslabel=this.$element.find(".grid-pages"),this.$countlabel=this.$element.find(".grid-count"),this.$startlabel=this.$element.find(".grid-start"),this.$endlabel=this.$element.find(".grid-end"),this.$tbody=b("<tbody>").insertAfter(this.$thead),this.$colheader=b("<tr>").appendTo(this.$thead),this.options=b.extend(!0,{},b.fn.datagrid.defaults,c),this.$pagesize.hasClass("select")?this.options.dataOptions.pageSize=parseInt(this.$pagesize.select("selectedItem").value,10):this.options.dataOptions.pageSize=parseInt(this.$pagesize.val(),10),this.$searchcontrol.length<=0&&(this.$searchcontrol=this.$element.find(".search")),this.columns=this.options.dataSource.columns(),this.$nextpagebtn.on("click",b.proxy(this.next,this)),this.$prevpagebtn.on("click",b.proxy(this.previous,this)),this.$searchcontrol.on("searched cleared",b.proxy(this.searchChanged,this)),this.$filtercontrol.on("changed",b.proxy(this.filterChanged,this)),this.$colheader.on("click","th",b.proxy(this.headerClicked,this)),this.$pagesize.hasClass("select")?this.$pagesize.on("changed",b.proxy(this.pagesizeChanged,this)):this.$pagesize.on("change",b.proxy(this.pagesizeChanged,this)),this.$pageinput.on("change",b.proxy(this.pageChanged,this)),this.renderColumns(),this.options.stretchHeight&&this.initStretchHeight(),this.renderData()};d.prototype={constructor:d,renderColumns:function(){var a=this;this.$footer.attr("colspan",this.columns.length),this.$topheader.attr("colspan",this.columns.length);var c="";b.each(this.columns,function(a,b){c+='<th data-property="'+b.property+'"',b.sortable&&(c+=' class="sortable"'),c+=">"+b.label+"</th>"}),a.$colheader.append(c)},updateColumns:function(a,b){this._updateColumns(this.$colheader,a,b),this.$sizingHeader&&this._updateColumns(this.$sizingHeader,this.$sizingHeader.find("th").eq(a.index()),b)},_updateColumns:function(a,c,d){var e=d==="asc"?"icon-chevron-up":"icon-chevron-down";a.find("i.datagrid-sort").remove(),a.find("th").removeClass("sorted"),b("<i>").addClass(e+" datagrid-sort").appendTo(c),c.addClass("sorted")},updatePageDropdown:function(a){var b="";for(var c=1;c<=a.pages;c++)b+="<li><a>"+c+"</a></li>";this.$pagedropdown.html(b)},updatePageButtons:function(a){a.page===1?this.$prevpagebtn.attr("disabled","disabled"):this.$prevpagebtn.removeAttr("disabled"),a.page===a.pages?this.$nextpagebtn.attr("disabled","disabled"):this.$nextpagebtn.removeAttr("disabled")},renderData:function(){var a=this;this.$tbody.html(this.placeholderRowHTML(this.options.loadingHTML)),this.options.dataSource.data(this.options.dataOptions,function(c){var d=c.count===1?a.options.itemText:a.options.itemsText,e="";a.$footerchildren.css("visibility",function(){return c.count>0?"visible":"hidden"}),a.$pageinput.val(c.page),a.$pageslabel.text(c.pages),a.$countlabel.text(c.count+" "+d),a.$startlabel.text(c.start),a.$endlabel.text(c.end),a.updatePageDropdown(c),a.updatePageButtons(c),b.each(c.data,function(c,d){e+="<tr>",b.each(a.columns,function(a,b){e+="<td>"+d[b.property]+"</td>"}),e+="</tr>"}),e||(e=a.placeholderRowHTML("0 "+a.options.itemsText)),a.$tbody.html(e),a.stretchHeight(),a.$element.trigger("loaded")})},placeholderRowHTML:function(a){return'<tr><td style="text-align:center;padding:20px;border-bottom:none;" colspan="'+this.columns.length+'">'+a+"</td></tr>"},headerClicked:function(a){var c=b(a.target);if(!c.hasClass("sortable"))return;var d=this.options.dataOptions.sortDirection,e=this.options.dataOptions.sortProperty,f=c.data("property");e===f?this.options.dataOptions.sortDirection=d==="asc"?"desc":"asc":(this.options.dataOptions.sortDirection="asc",this.options.dataOptions.sortProperty=f),this.options.dataOptions.pageIndex=0,this.updateColumns(c,this.options.dataOptions.sortDirection),this.renderData()},pagesizeChanged:function(a,c){c?this.options.dataOptions.pageSize=parseInt(c.value,10):this.options.dataOptions.pageSize=parseInt(b(a.target).val(),10),this.options.dataOptions.pageIndex=0,this.renderData()},pageChanged:function(a){var c=parseInt(b(a.target).val(),10);c=isNaN(c)?1:c;var d=this.$pageslabel.text();this.options.dataOptions.pageIndex=c>d?d-1:c-1,this.renderData()},searchChanged:function(a,b){this.options.dataOptions.search=b,this.options.dataOptions.pageIndex=0,this.renderData()},filterChanged:function(a,b){this.options.dataOptions.filter=b,this.options.dataOptions.pageIndex=0,this.renderData()},previous:function(){this.$nextpagebtn.attr("disabled","disabled"),this.$prevpagebtn.attr("disabled","disabled"),this.options.dataOptions.pageIndex--,this.renderData()},next:function(){this.$nextpagebtn.attr("disabled","disabled"),this.$prevpagebtn.attr("disabled","disabled"),this.options.dataOptions.pageIndex++,this.renderData()},reload:function(){this.options.dataOptions.pageIndex=0,this.renderData()},initStretchHeight:function(){this.$gridContainer=this.$element.parent(),this.$element.wrap('<div class="datagrid-stretch-wrapper">'),this.$stretchWrapper=this.$element.parent(),this.$headerTable=b("<table>").attr("class",this.$element.attr("class")),this.$footerTable=this.$headerTable.clone(),this.$headerTable.prependTo(this.$gridContainer).addClass("datagrid-stretch-header"),this.$thead.detach().appendTo(this.$headerTable),this.$sizingHeader=this.$thead.clone(),this.$sizingHeader.find("tr:first").remove(),this.$footerTable.appendTo(this.$gridContainer).addClass("datagrid-stretch-footer"),this.$tfoot.detach().appendTo(this.$footerTable)},stretchHeight:function(){if(!this.$gridContainer)return;this.setColumnWidths();var a=this.$gridContainer.height(),b=this.$headerTable.outerHeight(),c=this.$footerTable.outerHeight(),d=b+c;this.$stretchWrapper.height(a-d)},setColumnWidths:function(){function e(e,f){if(e===d-1)return;var g=b(f),h=a.eq(e),i=h.width();h.hasClass("sorted")&&g.prop("tagName")==="TD"&&(i=i+c),g.width(i)}if(!this.$sizingHeader)return;this.$element.prepend(this.$sizingHeader);var a=this.$sizingHeader.find("th"),d=a.length;this.$colheader.find("th").each(e),this.$tbody.find("tr:first > td").each(e),this.$sizingHeader.detach()}},b.fn.datagrid=function(a){return this.each(function(){var c=b(this),e=c.data("datagrid"),f=typeof a=="object"&&a;e||c.data("datagrid",e=new d(this,f)),typeof a=="string"&&e[a]()})},b.fn.datagrid.defaults={dataOptions:{pageIndex:0,pageSize:10},loadingHTML:'<div class="progress progress-striped active" style="width:50%;margin:auto;"><div class="bar" style="width:100%;"></div></div>',itemsText:"items",itemText:"item"},b.fn.datagrid.Constructor=d}),define("fuelux/pillbox",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.pillbox.defaults,c),this.$element.on("click","li",b.proxy(this.itemclicked,this))};c.prototype={constructor:c,items:function(){return this.$element.find("li").map(function(){var a=b(this);return b.extend({text:a.text()},a.data())}).get()},itemclicked:function(a){b(a.currentTarget).remove(),a.preventDefault()}},b.fn.pillbox=function(a){var d,e=this.each(function(){var e=b(this),f=e.data("pillbox"),g=typeof a=="object"&&a;f||e.data("pillbox",f=new c(this,g)),typeof a=="string"&&(d=f[a]())});return d===undefined?e:d},b.fn.pillbox.defaults={},b.fn.pillbox.Constructor=c,b(function(){b("body").on("mousedown.pillbox.data-api",".pillbox",function(a){var c=b(this);if(c.data("pillbox"))return;c.pillbox(c.data())})})}),define("fuelux/radio",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.radio.defaults,c),this.$label=this.$element.parent(),this.$icon=this.$label.find("i"),this.$radio=this.$label.find("input[type=radio]"),this.groupName=this.$radio.attr("name"),this.setState(this.$radio),this.$radio.on("change",b.proxy(this.itemchecked,this))};c.prototype={constructor:c,setState:function(a,b){var c=a.is(":checked"),d=a.is(":disabled");c===!0&&this.$icon.addClass("checked"),d===!0&&this.$icon.addClass("disabled")},resetGroup:function(){b("input[name="+this.groupName+"]").next().removeClass("checked")},enable:function(){this.$radio.attr("disabled",!1),this.$icon.removeClass("disabled")},disable:function(){this.$radio.attr("disabled",!0),this.$icon.addClass("disabled")},itemchecked:function(a){var c=b(a.target);this.resetGroup(),this.setState(c)}},b.fn.radio=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("radio"),h=typeof a=="object"&&a;g||f.data("radio",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.radio.defaults={},b.fn.radio.Constructor=c,b(function(){b(window).on("load",function(){b(".radio-custom > input[type=radio]").each(function(){var a=b(this);if(a.data("radio"))return;a.radio(a.data())})})})}),define("fuelux/search",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.search.defaults,c),this.$button=this.$element.find("button").on("click",b.proxy(this.buttonclicked,this)),this.$input=this.$element.find("input").on("keydown",b.proxy(this.keypress,this)).on("keyup",b.proxy(this.keypressed,this)),this.$icon=this.$element.find("i"),this.activeSearch=""};c.prototype={constructor:c,search:function(a){this.$icon.attr("class","icon-remove"),this.activeSearch=a,this.$element.trigger("searched",a)},clear:function(){this.$icon.attr("class","icon-search"),this.activeSearch="",this.$input.val(""),this.$element.trigger("cleared")},action:function(){var a=this.$input.val(),b=a===""||a===this.activeSearch;this.activeSearch&&b?this.clear():a&&this.search(a)},buttonclicked:function(a){a.preventDefault();if(b(a.currentTarget).is(".disabled, :disabled"))return;this.action()},keypress:function(a){a.which===13&&a.preventDefault()},keypressed:function(a){var b,c;a.which===13?(a.preventDefault(),this.action()):(b=this.$input.val(),c=b&&b===this.activeSearch,this.$icon.attr("class",c?"icon-remove":"icon-search"))},disable:function(){this.$input.attr("disabled","disabled"),this.$button.addClass("disabled")},enable:function(){this.$input.removeAttr("disabled"),this.$button.removeClass("disabled")}},b.fn.search=function(a){return this.each(function(){var d=b(this),e=d.data("search"),f=typeof a=="object"&&a;e||d.data("search",e=new c(this,f)),typeof a=="string"&&e[a]()})},b.fn.search.defaults={},b.fn.search.Constructor=c,b(function(){b("body").on("mousedown.search.data-api",".search",function(){var a=b(this);if(a.data("search"))return;a.search(a.data())})})}),define("fuelux/spinner",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.spinner.defaults,c),this.$input=this.$element.find(".spinner-input"),this.$element.on("keyup",this.$input,b.proxy(this.change,this)),this.options.hold?(this.$element.on("mousedown",".spinner-up",b.proxy(function(){this.startSpin(!0)},this)),this.$element.on("mouseup",".spinner-up, .spinner-down",b.proxy(this.stopSpin,this)),this.$element.on("mouseout",".spinner-up, .spinner-down",b.proxy(this.stopSpin,this)),this.$element.on("mousedown",".spinner-down",b.proxy(function(){this.startSpin(!1)},this))):(this.$element.on("click",".spinner-up",b.proxy(function(){this.step(!0)},this)),this.$element.on("click",".spinner-down",b.proxy(function(){this.step(!1)},this))),this.switches={count:1,enabled:!0},this.options.speed==="medium"?this.switches.speed=300:this.options.speed==="fast"?this.switches.speed=100:this.switches.speed=500,this.lastValue=null,this.render(),this.options.disabled&&this.disable()};c.prototype={constructor:c,render:function(){this.$input.val(this.options.value),this.$input.attr("maxlength",(this.options.max+"").split("").length)},change:function(){var a=this.$input.val();a/1?this.options.value=a/1:(a=a.replace(/[^0-9]/g,""),this.$input.val(a),this.options.value=a/1),this.triggerChangedEvent()},stopSpin:function(){clearTimeout(this.switches.timeout),this.switches.count=1,this.triggerChangedEvent()},triggerChangedEvent:function(){var a=this.value();if(a===this.lastValue)return;this.lastValue=a,this.$element.trigger("changed",a),this.$element.trigger("change")},startSpin:function(a){if(!this.options.disabled){var c=this.switches.count;c===1?(this.step(a),c=1):c<3?c=1.5:c<8?c=2.5:c=4,this.switches.timeout=setTimeout(b.proxy(function(){this.iterator(a)},this),this.switches.speed/c),this.switches.count++}},iterator:function(a){this.step(a),this.startSpin(a)},step:function(a){var b=this.options.value,c=a?this.options.max:this.options.min;if(a?b<c:b>c){var d=b+(a?1:-1)*this.options.step;(a?d>c:d<c)?this.value(c):this.value(d)}},value:function(a){return!isNaN(parseFloat(a))&&isFinite(a)?(a=parseFloat(a),this.options.value=a,this.$input.val(a),this):this.options.value},disable:function(){this.options.disabled=!0,this.$input.attr("disabled",""),this.$element.find("button").addClass("disabled")},enable:function(){this.options.disabled=!1,this.$input.removeAttr("disabled"),this.$element.find("button").removeClass("disabled")}},b.fn.spinner=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("spinner"),h=typeof a=="object"&&a;g||f.data("spinner",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.spinner.defaults={value:1,min:1,max:999,step:1,hold:!0,speed:"medium",disabled:!1},b.fn.spinner.Constructor=c,b(function(){b("body").on("mousedown.spinner.data-api",".spinner",function(a){var c=b(this);if(c.data("spinner"))return;c.spinner(c.data())})})}),define("fuelux/select",["require","jquery","./util"],function(a){var b=a("jquery");a("./util");var c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.select.defaults,c),this.$element.on("click","a",b.proxy(this.itemclicked,this)),this.$button=this.$element.find(".btn"),this.$label=this.$element.find(".dropdown-label"),this.setDefaultSelection(),c.resize==="auto"&&this.resize()};c.prototype={constructor:c,itemclicked:function(a){this.$selectedItem=b(a.target).parent(),this.$label.text(this.$selectedItem.text());var c=this.selectedItem();this.$element.trigger("changed",c),a.preventDefault()},resize:function(){var a=b("#selectTextSize")[0];a||b("<div/>").attr({id:"selectTextSize"}).appendTo("body");var c=0,d=0;this.$element.find("a").each(function(){var a=b(this),e=a.text(),f=b("#selectTextSize");f.text(e),d=f.outerWidth(),d>c&&(c=d)}),this.$label.width(c)},selectedItem:function(){var a=this.$selectedItem.text();return b.extend({text:a},this.$selectedItem.data())},selectByText:function(a){var b="li a:fuelTextExactCI("+a+")";this.selectBySelector(b)},selectByValue:function(a){var b='li[data-value="'+a+'"]';this.selectBySelector(b)},selectByIndex:function(a){var b="li:eq("+a+")";this.selectBySelector(b)},selectBySelector:function(a){var b=this.$element.find(a);this.$selectedItem=b,this.$label.text(this.$selectedItem.text())},setDefaultSelection:function(){var a="li[data-selected=true]:first",b=this.$element.find(a);b.length===0?this.selectByIndex(0):(this.selectBySelector(a),b.removeData("selected"),b.removeAttr("data-selected"))},enable:function(){this.$button.removeClass("disabled")},disable:function(){this.$button.addClass("disabled")}},b.fn.select=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("select"),h=typeof a=="object"&&a;g||f.data("select",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.select.defaults={},b.fn.select.Constructor=c,b(function(){b(window).on("load",function(){b(".select").each(function(){var a=b(this);if(a.data("select"))return;a.select(a.data())})}),b("body").on("mousedown.select.data-api",".select",function(a){var c=b(this);if(c.data("select"))return;c.select(c.data())})})}),define("fuelux/tree",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.tree.defaults,c),this.$element.on("click",".tree-item",b.proxy(function(a){this.selectItem(a.currentTarget)},this)),this.$element.on("click",".tree-folder-header",b.proxy(function(a){this.selectFolder(a.currentTarget)},this)),this.render()};c.prototype={constructor:c,render:function(){this.populate(this.$element)},populate:function(a){var c=this,d=a.parent().find(".tree-loader:eq(0)");d.show(),this.options.dataSource.data(a.data(),function(e){d.hide(),b.each(e.data,function(b,d){var e;d.type==="folder"?(e=c.$element.find(".tree-folder:eq(0)").clone().show(),e.find(".tree-folder-name").html(d.name),e.find(".tree-loader").html(c.options.loadingHTML),e.find(".tree-folder-header").data(d)):d.type==="item"&&(e=c.$element.find(".tree-item:eq(0)").clone().show(),e.find(".tree-item-name").html(d.name),e.data(d)),a.hasClass("tree-folder-header")?a.parent().find(".tree-folder-content:eq(0)").append(e):a.append(e)}),c.$element.trigger("loaded")})},selectItem:function(a){var c=b(a),d=this.$element.find(".tree-selected"),e=[];this.options.multiSelect?b.each(d,function(a,d){var f=b(d);f[0]!==c[0]&&e.push(b(d).data())}):d[0]!==c[0]&&(d.removeClass("tree-selected").find("i").removeClass("icon-ok").addClass("tree-dot"),e.push(c.data())),c.hasClass("tree-selected")?(c.removeClass("tree-selected"),c.find("i").removeClass("icon-ok").addClass("tree-dot")):(c.addClass("tree-selected"),c.find("i").removeClass("tree-dot").addClass("icon-ok"),this.options.multiSelect&&e.push(c.data())),e.length&&this.$element.trigger("selected",{info:e})},selectFolder:function(a){var c=b(a),d=c.parent();c.find(".icon-folder-close").length?(d.find(".tree-folder-content").children().length?d.find(".tree-folder-content:eq(0)").show():this.populate(c),d.find(".icon-folder-close:eq(0)").removeClass("icon-folder-close").addClass("icon-folder-open"),this.$element.trigger("opened",c.data())):(this.options.cacheItems?d.find(".tree-folder-content:eq(0)").hide():d.find(".tree-folder-content:eq(0)").empty(),d.find(".icon-folder-open:eq(0)").removeClass("icon-folder-open").addClass("icon-folder-close"),this.$element.trigger("closed",c.data()))},selectedItems:function(){var a=this.$element.find(".tree-selected"),c=[];return b.each(a,function(a,d){c.push(b(d).data())}),c}},b.fn.tree=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("tree"),h=typeof a=="object"&&a;g||f.data("tree",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.tree.defaults={multiSelect:!1,loadingHTML:"<div>Loading...</div>",cacheItems:!0},b.fn.tree.Constructor=c}),define("fuelux/wizard",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){var d;this.$element=b(a),this.options=b.extend({},b.fn.wizard.defaults,c),this.currentStep=1,this.numSteps=this.$element.find("li").length,this.$prevBtn=this.$element.find("button.btn-prev"),this.$nextBtn=this.$element.find("button.btn-next"),d=this.$nextBtn.children().detach(),this.nextText=b.trim(this.$nextBtn.text()),this.$nextBtn.append(d),this.$prevBtn.on("click",b.proxy(this.previous,this)),this.$nextBtn.on("click",b.proxy(this.next,this)),this.$element.on("click","li.complete",b.proxy(this.stepclicked,this))};c.prototype={constructor:c,setState:function(){var a=this.currentStep>1,c=this.currentStep===1,d=this.currentStep===this.numSteps;this.$prevBtn.attr("disabled",c===!0||a===!1);var e=this.$nextBtn.data();if(e&&e.last){this.lastText=e.last;if(typeof this.lastText!="undefined"){var f=d!==!0?this.nextText:this.lastText,g=this.$nextBtn.children().detach();this.$nextBtn.text(f).append(g)}}var h=this.$element.find("li");h.removeClass("active").removeClass("complete"),h.find("span.badge").removeClass("badge-info").removeClass("badge-success");var i="li:lt("+(this.currentStep-1)+")",j=this.$element.find(i);j.addClass("complete"),j.find("span.badge").addClass("badge-success");var k="li:eq("+(this.currentStep-1)+")",l=this.$element.find(k);l.addClass("active"),l.find("span.badge").addClass("badge-info");var m=l.data().target;b(".step-pane").removeClass("active"),b(m).addClass("active"),this.$element.trigger("changed")},stepclicked:function(a){var c=b(a.currentTarget),d=b(".steps li").index(c),e=b.Event("stepclick");this.$element.trigger(e,{step:d+1});if(e.isDefaultPrevented())return;this.currentStep=d+1,this.setState()},previous:function(){var a=this.currentStep>1;if(a){var c=b.Event("change");this.$element.trigger(c,{step:this.currentStep,direction:"previous"});if(c.isDefaultPrevented())return;this.currentStep-=1,this.setState()}},next:function(){var a=this.currentStep+1<=this.numSteps,c=this.currentStep===this.numSteps;if(a){var d=b.Event("change");this.$element.trigger(d,{step:this.currentStep,direction:"next"});if(d.isDefaultPrevented())return;this.currentStep+=1,this.setState()}else c&&this.$element.trigger("finished")},selectedItem:function(a){return{step:this.currentStep}}},b.fn.wizard=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("wizard"),h=typeof a=="object"&&a;g||f.data("wizard",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.wizard.defaults={},b.fn.wizard.Constructor=c,b(function(){b("body").on("mousedown.wizard.data-api",".wizard",function(){var a=b(this);if(a.data("wizard"))return;a.wizard(a.data())})})}),define("fuelux/all",["require","jquery","bootstrap/bootstrap-affix","bootstrap/bootstrap-alert","bootstrap/bootstrap-button","bootstrap/bootstrap-carousel","bootstrap/bootstrap-collapse","bootstrap/bootstrap-dropdown","bootstrap/bootstrap-modal","bootstrap/bootstrap-popover","bootstrap/bootstrap-scrollspy","bootstrap/bootstrap-tab","bootstrap/bootstrap-tooltip","bootstrap/bootstrap-transition","bootstrap/bootstrap-typeahead","fuelux/checkbox","fuelux/combobox","fuelux/datagrid","fuelux/pillbox","fuelux/radio","fuelux/search","fuelux/spinner","fuelux/select","fuelux/tree","fuelux/wizard"],function(a){a("jquery"),a("bootstrap/bootstrap-affix"),a("bootstrap/bootstrap-alert"),a("bootstrap/bootstrap-button"),a("bootstrap/bootstrap-carousel"),a("bootstrap/bootstrap-collapse"),a("bootstrap/bootstrap-dropdown"),a("bootstrap/bootstrap-modal"),a("bootstrap/bootstrap-popover"),a("bootstrap/bootstrap-scrollspy"),a("bootstrap/bootstrap-tab"),a("bootstrap/bootstrap-tooltip"),a("bootstrap/bootstrap-transition"),a("bootstrap/bootstrap-typeahead"),a("fuelux/checkbox"),a("fuelux/combobox"),a("fuelux/datagrid"),a("fuelux/pillbox"),a("fuelux/radio"),a("fuelux/search"),a("fuelux/spinner"),a("fuelux/select"),a("fuelux/tree"),a("fuelux/wizard")})})();
\ No newline at end of file
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/checkbox.js b/opendaylight/web/root/src/main/resources/js/fuelux/checkbox.js
new file mode 100755 (executable)
index 0000000..639300e
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Fuel UX Checkbox
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery'],function (require) {
+
+       var $ = require('jquery');
+
+
+       // CHECKBOX CONSTRUCTOR AND PROTOTYPE
+
+       var Checkbox = function (element, options) {
+
+               this.$element = $(element);
+               this.options = $.extend({}, $.fn.checkbox.defaults, options);
+
+               // cache elements
+               this.$label = this.$element.parent();
+               this.$icon = this.$label.find('i');
+               this.$chk = this.$label.find('input[type=checkbox]');
+
+               // set default state
+               this.setState(this.$chk);
+
+               // handle events
+               this.$chk.on('change', $.proxy(this.itemchecked, this));
+       };
+
+       Checkbox.prototype = {
+
+               constructor: Checkbox,
+
+               setState: function ($chk) {
+                       var checked = $chk.is(':checked');
+                       var disabled = $chk.is(':disabled');
+
+                       // reset classes
+                       this.$icon.removeClass('checked').removeClass('disabled');
+
+                       // set state of checkbox
+                       if (checked === true) {
+                               this.$icon.addClass('checked');
+                       }
+                       if (disabled === true) {
+                               this.$icon.addClass('disabled');
+                       }
+               },
+
+               enable: function () {
+                       this.$chk.attr('disabled', false);
+                       this.$icon.removeClass('disabled');
+               },
+
+               disable: function () {
+                       this.$chk.attr('disabled', true);
+                       this.$icon.addClass('disabled');
+               },
+
+               toggle: function () {
+                       this.$chk.click();
+               },
+
+               itemchecked: function (e) {
+                       var chk = $(e.target);
+                       this.setState(chk);
+               }
+       };
+
+
+       // CHECKBOX PLUGIN DEFINITION
+
+       $.fn.checkbox = function (option, value) {
+               var methodReturn;
+
+               var $set = this.each(function () {
+                       var $this = $(this);
+                       var data = $this.data('checkbox');
+                       var options = typeof option === 'object' && option;
+
+                       if (!data) $this.data('checkbox', (data = new Checkbox(this, options)));
+                       if (typeof option === 'string') methodReturn = data[option](value);
+               });
+
+               return (methodReturn === undefined) ? $set : methodReturn;
+       };
+
+       $.fn.checkbox.defaults = {};
+
+       $.fn.checkbox.Constructor = Checkbox;
+
+
+       // CHECKBOX DATA-API
+
+       $(function () {
+               $(window).on('load', function () {
+                       //$('i.checkbox').each(function () {
+                       $('.checkbox-custom > input[type=checkbox]').each(function () {
+                               var $this = $(this);
+                               if ($this.data('checkbox')) return;
+                               $this.checkbox($this.data());
+                       });
+               });
+       });
+
+});
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/combobox.js b/opendaylight/web/root/src/main/resources/js/fuelux/combobox.js
new file mode 100755 (executable)
index 0000000..1d0a132
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Fuel UX Combobox
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery','./util'],function (require) {
+
+       var $ = require('jquery');
+       require('./util');
+
+       // COMBOBOX CONSTRUCTOR AND PROTOTYPE
+
+       var Combobox = function (element, options) {
+               this.$element = $(element);
+               this.options = $.extend({}, $.fn.combobox.defaults, options);
+               this.$element.on('click', 'a', $.proxy(this.itemclicked, this));
+               this.$element.on('change', 'input', $.proxy(this.inputchanged, this));
+               this.$input = this.$element.find('input');
+               this.$button = this.$element.find('.btn');
+
+               // set default selection
+               this.setDefaultSelection();
+       };
+
+       Combobox.prototype = {
+
+               constructor: Combobox,
+
+               selectedItem: function () {
+                       var item = this.$selectedItem;
+                       var data = {};
+
+                       if (item) {
+                               var txt = this.$selectedItem.text();
+                               data = $.extend({ text: txt }, this.$selectedItem.data());
+                       }
+                       else {
+                               data = { text: this.$input.val()};
+                       }
+
+                       return data;
+               },
+
+               selectByText: function (text) {
+                       var selector = 'li:fuelTextExactCI(' + text + ')';
+                       this.selectBySelector(selector);
+               },
+
+               selectByValue: function (value) {
+                       var selector = 'li[data-value="' + value + '"]';
+                       this.selectBySelector(selector);
+               },
+
+               selectByIndex: function (index) {
+                       // zero-based index
+                       var selector = 'li:eq(' + index + ')';
+                       this.selectBySelector(selector);
+               },
+
+               selectBySelector: function (selector) {
+                       var $item = this.$element.find(selector);
+
+                       if (typeof $item[0] !== 'undefined') {
+                               this.$selectedItem = $item;
+                               this.$input.val(this.$selectedItem.text());
+                       }
+                       else {
+                               this.$selectedItem = null;
+                       }
+               },
+
+               setDefaultSelection: function () {
+                       var selector = 'li[data-selected=true]:first';
+                       var item = this.$element.find(selector);
+
+                       if (item.length > 0) {
+                               // select by data-attribute
+                               this.selectBySelector(selector);
+                               item.removeData('selected');
+                               item.removeAttr('data-selected');
+                       }
+               },
+
+               enable: function () {
+                       this.$input.removeAttr('disabled');
+                       this.$button.removeClass('disabled');
+               },
+
+               disable: function () {
+                       this.$input.attr('disabled', true);
+                       this.$button.addClass('disabled');
+               },
+
+               itemclicked: function (e) {
+                       this.$selectedItem = $(e.target).parent();
+
+                       // set input text and trigger input change event marked as synthetic
+                       this.$input.val(this.$selectedItem.text()).trigger('change', { synthetic: true });
+
+                       // pass object including text and any data-attributes
+                       // to onchange event
+                       var data = this.selectedItem();
+
+                       // trigger changed event
+                       this.$element.trigger('changed', data);
+
+                       e.preventDefault();
+               },
+
+               inputchanged: function (e, extra) {
+
+                       // skip processing for internally-generated synthetic event
+                       // to avoid double processing
+                       if (extra && extra.synthetic) return;
+
+                       var val = $(e.target).val();
+                       this.selectByText(val);
+
+                       // find match based on input
+                       // if no match, pass the input value
+                       var data = this.selectedItem();
+                       if (data.text.length === 0) {
+                               data = { text: val };
+                       }
+
+                       // trigger changed event
+                       this.$element.trigger('changed', data);
+
+               }
+
+       };
+
+
+       // COMBOBOX PLUGIN DEFINITION
+
+       $.fn.combobox = function (option, value) {
+               var methodReturn;
+
+               var $set = this.each(function () {
+                       var $this = $(this);
+                       var data = $this.data('combobox');
+                       var options = typeof option === 'object' && option;
+
+                       if (!data) $this.data('combobox', (data = new Combobox(this, options)));
+                       if (typeof option === 'string') methodReturn = data[option](value);
+               });
+
+               return (methodReturn === undefined) ? $set : methodReturn;
+       };
+
+       $.fn.combobox.defaults = {};
+
+       $.fn.combobox.Constructor = Combobox;
+
+
+       // COMBOBOX DATA-API
+
+       $(function () {
+
+               $(window).on('load', function () {
+                       $('.combobox').each(function () {
+                               var $this = $(this);
+                               if ($this.data('combobox')) return;
+                               $this.combobox($this.data());
+                       });
+               });
+
+               $('body').on('mousedown.combobox.data-api', '.combobox', function (e) {
+                       var $this = $(this);
+                       if ($this.data('combobox')) return;
+                       $this.combobox($this.data());
+               });
+       });
+
+});
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/datagrid.js b/opendaylight/web/root/src/main/resources/js/fuelux/datagrid.js
new file mode 100755 (executable)
index 0000000..e051928
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Fuel UX Datagrid
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery'],function(require) {
+
+       var $ = require('jquery');
+
+       // Relates to thead .sorted styles in datagrid.less
+       var SORTED_HEADER_OFFSET = 22;
+
+
+       // DATAGRID CONSTRUCTOR AND PROTOTYPE
+
+       var Datagrid = function (element, options) {
+               this.$element = $(element);
+               this.$thead = this.$element.find('thead');
+               this.$tfoot = this.$element.find('tfoot');
+               this.$footer = this.$element.find('tfoot th');
+               this.$footerchildren = this.$footer.children().show().css('visibility', 'hidden');
+               this.$topheader = this.$element.find('thead th');
+               this.$searchcontrol = this.$element.find('.datagrid-search');
+               this.$filtercontrol = this.$element.find('.filter');
+               this.$pagesize = this.$element.find('.grid-pagesize');
+               this.$pageinput = this.$element.find('.grid-pager input');
+               this.$pagedropdown = this.$element.find('.grid-pager .dropdown-menu');
+               this.$prevpagebtn = this.$element.find('.grid-prevpage');
+               this.$nextpagebtn = this.$element.find('.grid-nextpage');
+               this.$pageslabel = this.$element.find('.grid-pages');
+               this.$countlabel = this.$element.find('.grid-count');
+               this.$startlabel = this.$element.find('.grid-start');
+               this.$endlabel = this.$element.find('.grid-end');
+
+               this.$tbody = $('<tbody>').insertAfter(this.$thead);
+               this.$colheader = $('<tr>').appendTo(this.$thead);
+
+               this.options = $.extend(true, {}, $.fn.datagrid.defaults, options);
+
+               // Shim until v3 -- account for FuelUX select or native select for page size:
+               if (this.$pagesize.hasClass('select')) {
+                       this.options.dataOptions.pageSize = parseInt(this.$pagesize.select('selectedItem').value, 10);
+               } else {
+                       this.options.dataOptions.pageSize = parseInt(this.$pagesize.val(), 10);
+               }
+
+               // Shim until v3 -- account for older search class:
+               if (this.$searchcontrol.length <= 0) {
+                       this.$searchcontrol = this.$element.find('.search');
+               }
+
+               this.columns = this.options.dataSource.columns();
+
+               this.$nextpagebtn.on('click', $.proxy(this.next, this));
+               this.$prevpagebtn.on('click', $.proxy(this.previous, this));
+               this.$searchcontrol.on('searched cleared', $.proxy(this.searchChanged, this));
+               this.$filtercontrol.on('changed', $.proxy(this.filterChanged, this));
+               this.$colheader.on('click', 'th', $.proxy(this.headerClicked, this));
+
+               if(this.$pagesize.hasClass('select')) {
+                       this.$pagesize.on('changed', $.proxy(this.pagesizeChanged, this));
+               } else {
+                       this.$pagesize.on('change', $.proxy(this.pagesizeChanged, this));
+               }
+
+               this.$pageinput.on('change', $.proxy(this.pageChanged, this));
+
+               this.renderColumns();
+
+               if (this.options.stretchHeight) this.initStretchHeight();
+
+               this.renderData();
+       };
+
+       Datagrid.prototype = {
+
+               constructor: Datagrid,
+
+               renderColumns: function () {
+                       var self = this;
+
+                       this.$footer.attr('colspan', this.columns.length);
+                       this.$topheader.attr('colspan', this.columns.length);
+
+                       var colHTML = '';
+
+                       $.each(this.columns, function (index, column) {
+                               colHTML += '<th data-property="' + column.property + '"';
+                               if (column.sortable) colHTML += ' class="sortable"';
+                               colHTML += '>' + column.label + '</th>';
+                       });
+
+                       self.$colheader.append(colHTML);
+               },
+
+               updateColumns: function ($target, direction) {
+                       this._updateColumns(this.$colheader, $target, direction);
+
+                       if (this.$sizingHeader) {
+                               this._updateColumns(this.$sizingHeader, this.$sizingHeader.find('th').eq($target.index()), direction);
+                       }
+               },
+
+               _updateColumns: function ($header, $target, direction) {
+                       var className = (direction === 'asc') ? 'icon-chevron-up' : 'icon-chevron-down';
+                       $header.find('i.datagrid-sort').remove();
+                       $header.find('th').removeClass('sorted');
+                       $('<i>').addClass(className + ' datagrid-sort').appendTo($target);
+                       $target.addClass('sorted');
+               },
+
+               updatePageDropdown: function (data) {
+                       var pageHTML = '';
+
+                       for (var i = 1; i <= data.pages; i++) {
+                               pageHTML += '<li><a>' + i + '</a></li>';
+                       }
+
+                       this.$pagedropdown.html(pageHTML);
+               },
+
+               updatePageButtons: function (data) {
+                       if (data.page === 1) {
+                               this.$prevpagebtn.attr('disabled', 'disabled');
+                       } else {
+                               this.$prevpagebtn.removeAttr('disabled');
+                       }
+
+                       if (data.page === data.pages) {
+                               this.$nextpagebtn.attr('disabled', 'disabled');
+                       } else {
+                               this.$nextpagebtn.removeAttr('disabled');
+                       }
+               },
+
+               renderData: function () {
+                       var self = this;
+
+                       this.$tbody.html(this.placeholderRowHTML(this.options.loadingHTML));
+
+                       this.options.dataSource.data(this.options.dataOptions, function (data) {
+                               var itemdesc = (data.count === 1) ? self.options.itemText : self.options.itemsText;
+                               var rowHTML = '';
+
+                               self.$footerchildren.css('visibility', function () {
+                                       return (data.count > 0) ? 'visible' : 'hidden';
+                               });
+
+                               self.$pageinput.val(data.page);
+                               self.$pageslabel.text(data.pages);
+                               self.$countlabel.text(data.count + ' ' + itemdesc);
+                               self.$startlabel.text(data.start);
+                               self.$endlabel.text(data.end);
+
+                               self.updatePageDropdown(data);
+                               self.updatePageButtons(data);
+
+                               $.each(data.data, function (index, row) {
+                                       rowHTML += '<tr>';
+                                       $.each(self.columns, function (index, column) {
+                                               rowHTML += '<td>' + row[column.property] + '</td>';
+                                       });
+                                       rowHTML += '</tr>';
+                               });
+
+                               if (!rowHTML) rowHTML = self.placeholderRowHTML('0 ' + self.options.itemsText);
+
+                               self.$tbody.html(rowHTML);
+                               self.stretchHeight();
+
+                               self.$element.trigger('loaded');
+                       });
+
+               },
+
+               placeholderRowHTML: function (content) {
+                       return '<tr><td style="text-align:center;padding:20px;border-bottom:none;" colspan="' +
+                               this.columns.length + '">' + content + '</td></tr>';
+               },
+
+               headerClicked: function (e) {
+                       var $target = $(e.target);
+                       if (!$target.hasClass('sortable')) return;
+
+                       var direction = this.options.dataOptions.sortDirection;
+                       var sort = this.options.dataOptions.sortProperty;
+                       var property = $target.data('property');
+
+                       if (sort === property) {
+                               this.options.dataOptions.sortDirection = (direction === 'asc') ? 'desc' : 'asc';
+                       } else {
+                               this.options.dataOptions.sortDirection = 'asc';
+                               this.options.dataOptions.sortProperty = property;
+                       }
+
+                       this.options.dataOptions.pageIndex = 0;
+                       this.updateColumns($target, this.options.dataOptions.sortDirection);
+                       this.renderData();
+               },
+
+               pagesizeChanged: function (e, pageSize) {
+                       if(pageSize) {
+                               this.options.dataOptions.pageSize = parseInt(pageSize.value, 10);
+                       } else {
+                               this.options.dataOptions.pageSize = parseInt($(e.target).val(), 10);
+                       }
+
+                       this.options.dataOptions.pageIndex = 0;
+                       this.renderData();
+               },
+
+               pageChanged: function (e) {
+                       var pageRequested = parseInt($(e.target).val(), 10);
+                       pageRequested = (isNaN(pageRequested)) ? 1 : pageRequested;
+                       var maxPages = this.$pageslabel.text();
+               
+                       this.options.dataOptions.pageIndex = 
+                               (pageRequested > maxPages) ? maxPages - 1 : pageRequested - 1;
+
+                       this.renderData();
+               },
+
+               searchChanged: function (e, search) {
+                       this.options.dataOptions.search = search;
+                       this.options.dataOptions.pageIndex = 0;
+                       this.renderData();
+               },
+
+               filterChanged: function (e, filter) {
+                       this.options.dataOptions.filter = filter;
+                       this.options.dataOptions.pageIndex = 0;
+                       this.renderData();
+               },
+
+               previous: function () {
+                       this.$nextpagebtn.attr('disabled', 'disabled');
+                       this.$prevpagebtn.attr('disabled', 'disabled');
+                       this.options.dataOptions.pageIndex--;
+                       this.renderData();
+               },
+
+               next: function () {
+                       this.$nextpagebtn.attr('disabled', 'disabled');
+                       this.$prevpagebtn.attr('disabled', 'disabled');
+                       this.options.dataOptions.pageIndex++;
+                       this.renderData();
+               },
+
+               reload: function () {
+                       this.options.dataOptions.pageIndex = 0;
+                       this.renderData();
+               },
+
+               initStretchHeight: function () {
+                       this.$gridContainer = this.$element.parent();
+
+                       this.$element.wrap('<div class="datagrid-stretch-wrapper">');
+                       this.$stretchWrapper = this.$element.parent();
+
+                       this.$headerTable = $('<table>').attr('class', this.$element.attr('class'));
+                       this.$footerTable = this.$headerTable.clone();
+
+                       this.$headerTable.prependTo(this.$gridContainer).addClass('datagrid-stretch-header');
+                       this.$thead.detach().appendTo(this.$headerTable);
+
+                       this.$sizingHeader = this.$thead.clone();
+                       this.$sizingHeader.find('tr:first').remove();
+
+                       this.$footerTable.appendTo(this.$gridContainer).addClass('datagrid-stretch-footer');
+                       this.$tfoot.detach().appendTo(this.$footerTable);
+               },
+
+               stretchHeight: function () {
+                       if (!this.$gridContainer) return;
+
+                       this.setColumnWidths();
+
+                       var targetHeight = this.$gridContainer.height();
+                       var headerHeight = this.$headerTable.outerHeight();
+                       var footerHeight = this.$footerTable.outerHeight();
+                       var overhead = headerHeight + footerHeight;
+
+                       this.$stretchWrapper.height(targetHeight - overhead);
+               },
+
+               setColumnWidths: function () {
+                       if (!this.$sizingHeader) return;
+
+                       this.$element.prepend(this.$sizingHeader);
+
+                       var $sizingCells = this.$sizingHeader.find('th');
+                       var columnCount = $sizingCells.length;
+
+                       function matchSizingCellWidth(i, el) {
+                               if (i === columnCount - 1) return;
+
+                               var $el = $(el);
+                               var $sourceCell = $sizingCells.eq(i);
+                               var width = $sourceCell.width();
+
+                               // TD needs extra width to match sorted column header
+                               if ($sourceCell.hasClass('sorted') && $el.prop('tagName') === 'TD') width = width + SORTED_HEADER_OFFSET;
+
+                               $el.width(width);
+                       }
+
+                       this.$colheader.find('th').each(matchSizingCellWidth);
+                       this.$tbody.find('tr:first > td').each(matchSizingCellWidth);
+
+                       this.$sizingHeader.detach();
+               }
+       };
+
+
+       // DATAGRID PLUGIN DEFINITION
+
+       $.fn.datagrid = function (option) {
+               return this.each(function () {
+                       var $this = $(this);
+                       var data = $this.data('datagrid');
+                       var options = typeof option === 'object' && option;
+
+                       if (!data) $this.data('datagrid', (data = new Datagrid(this, options)));
+                       if (typeof option === 'string') data[option]();
+               });
+       };
+
+       $.fn.datagrid.defaults = {
+               dataOptions: { pageIndex: 0, pageSize: 10 },
+               loadingHTML: '<div class="progress progress-striped active" style="width:50%;margin:auto;"><div class="bar" style="width:100%;"></div></div>',
+               itemsText: 'items',
+               itemText: 'item'
+       };
+
+       $.fn.datagrid.Constructor = Datagrid;
+
+});
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/loader.min.js b/opendaylight/web/root/src/main/resources/js/fuelux/loader.min.js
new file mode 100755 (executable)
index 0000000..fe68290
--- /dev/null
@@ -0,0 +1,4 @@
+/*! Fuel UX - v2.3.1 - 2013-08-02
+* https://github.com/ExactTarget/fuelux
+* Copyright (c) 2013 ExactTarget; Licensed MIT */
+(function(){var a,b,c;(function(d){function l(a,b){var c,d,e,f,g,h,j,k,l,m,n=b&&b.split("/"),o=i.map,p=o&&o["*"]||{};if(a&&a.charAt(0)==="."&&b){n=n.slice(0,n.length-1),a=n.concat(a.split("/"));for(k=0;k<a.length;k+=1){m=a[k];if(m===".")a.splice(k,1),k-=1;else if(m==="..")if(k!==1||a[2]!==".."&&a[0]!=="..")k>0&&(a.splice(k-1,2),k-=2);else break}a=a.join("/")}if((n||p)&&o){c=a.split("/");for(k=c.length;k>0;k-=1){d=c.slice(0,k).join("/");if(n)for(l=n.length;l>0;l-=1){e=o[n.slice(0,l).join("/")];if(e){e=e[d];if(e){f=e,g=k;break}}}if(f)break;!h&&p&&p[d]&&(h=p[d],j=k)}!f&&h&&(f=h,g=j),f&&(c.splice(0,g,f),a=c.join("/"))}return a}function m(a,b){return function(){return f.apply(d,k.call(arguments,0).concat([a,b]))}}function n(a){return function(b){return l(b,a)}}function o(a){return function(b){g[a]=b}}function p(a){if(h.hasOwnProperty(a)){var b=h[a];delete h[a],j[a]=!0,e.apply(d,b)}if(!g.hasOwnProperty(a))throw new Error("No "+a);return g[a]}function q(a,b){var c,d,e=a.indexOf("!");return e!==-1?(c=l(a.slice(0,e),b),a=a.slice(e+1),d=p(c),d&&d.normalize?a=d.normalize(a,n(b)):a=l(a,b)):a=l(a,b),{f:c?c+"!"+a:a,n:a,p:d}}function r(a){return function(){return i&&i.config&&i.config[a]||{}}}var e,f,g={},h={},i={},j={},k=[].slice;e=function(a,b,c,e){var f,i,k,l,n,s=[],t;e=e||a;if(typeof c=="function"){b=!b.length&&c.length?["require","exports","module"]:b;for(n=0;n<b.length;n+=1){l=q(b[n],e),i=l.f;if(i==="require")s[n]=m(a);else if(i==="exports")s[n]=g[a]={},t=!0;else if(i==="module")f=s[n]={id:a,uri:"",exports:g[a],config:r(a)};else if(g.hasOwnProperty(i)||h.hasOwnProperty(i))s[n]=p(i);else if(l.p)l.p.load(l.n,m(e,!0),o(i),{}),s[n]=g[i];else if(!j[i])throw new Error(a+" missing "+i)}k=c.apply(g[a],s);if(a)if(f&&f.exports!==d&&f.exports!==g[a])g[a]=f.exports;else if(k!==d||!t)g[a]=k}else a&&(g[a]=c)},a=b=f=function(a,b,c,g,h){return typeof a=="string"?p(q(a,b).f):(a.splice||(i=a,b.splice?(a=b,b=c,c=null):a=d),b=b||function(){},typeof c=="function"&&(c=g,g=h),g?e(d,a,b,c):setTimeout(function(){e(d,a,b,c)},15),f)},f.config=function(a){return i=a,f},c=function(a,b,c){b.splice||(c=b,b=[]),h[a]=[a,b,c]},c.amd={jQuery:!0}})(),c("almond",function(){}),function(a){var b;c("bootstrap/bootstrap-transition",["jquery"],function(){return function(){!function(a){a(function(){a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-affix",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.options=a.extend({},a.fn.affix.defaults,c),this.$window=a(window).on("scroll.affix.data-api",a.proxy(this.checkPosition,this)).on("click.affix.data-api",a.proxy(function(){setTimeout(a.proxy(this.checkPosition,this),1)},this)),this.$element=a(b),this.checkPosition()};b.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var b=a(document).height(),c=this.$window.scrollTop(),d=this.$element.offset(),e=this.options.offset,f=e.bottom,g=e.top,h="affix affix-top affix-bottom",i;typeof e!="object"&&(f=g=e),typeof g=="function"&&(g=e.top()),typeof f=="function"&&(f=e.bottom()),i=this.unpin!=null&&c+this.unpin<=d.top?!1:f!=null&&d.top+this.$element.height()>=b-f?"bottom":g!=null&&c<=g?"top":!1;if(this.affixed===i)return;this.affixed=i,this.unpin=i=="bottom"?d.top-c:null,this.$element.removeClass(h).addClass("affix"+(i?"-"+i:""))};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("affix"),f=typeof c=="object"&&c;e||d.data("affix",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.defaults={offset:0},a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-alert",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed").remove()}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.alert.data-api",b,c.prototype.close)}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-button",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a=a+"Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-carousel",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.prototype={cycle:function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(b){var c=this.getActiveIndex(),d=this;if(b>this.$items.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){d.to(b)}):c==b?this.pause().cycle():this.slide(b>c?"next":"prev",a(this.$items[b]))},pause:function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this,j;this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h](),j=a.Event("slide",{relatedTarget:e[0],direction:g});if(e.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")}));if(a.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(j);if(j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})}else{this.$element.trigger(j);if(j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=a.extend({},a.fn.carousel.defaults,typeof c=="object"&&c),g=typeof c=="string"?c:f.slide;e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.defaults={interval:5e3,pause:"hover"},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),c.data()),g;e.carousel(f),(g=c.attr("data-slide-to"))&&e.data("carousel").pause().to(g).cycle(),b.preventDefault()})}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-collapse",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b,c,d,e;if(this.transitioning||this.$element.hasClass("in"))return;b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find("> .accordion-group > .in");if(d&&d.length){e=d.data("collapse");if(e&&e.transitioning)return;d.collapse("hide"),e||d.data("collapse",null)}this.$element[b](0),this.transition("addClass",a.Event("show"),"shown"),a.support.transition&&this.$element[b](this.$element[0][c])},hide:function(){var b;if(this.transitioning||!this.$element.hasClass("in"))return;b=this.dimension(),this.reset(this.$element[b]()),this.transition("removeClass",a.Event("hide"),"hidden"),this.$element[b](0)},reset:function(a){var b=this.dimension();return this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("collapse"),this},transition:function(b,c,d){var e=this,f=function(){c.type=="show"&&e.reset(),e.transitioning=0,e.$element.trigger(d)};this.$element.trigger(c);if(c.isDefaultPrevented())return;this.transitioning=1,this.$element[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=a.extend({},a.fn.collapse.defaults,d.data(),typeof c=="object"&&c);e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();c[a(e).hasClass("in")?"addClass":"removeClass"]("collapsed"),a(e).collapse(f)})}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-dropdown",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){function d(){a(".dropdown-backdrop").remove(),a(b).each(function(){e(a(this)).removeClass("open")})}function e(b){var c=b.attr("data-target"),d;c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,"")),d=c&&a(c);if(!d||!d.length)d=b.parent();return d}var b="[data-toggle=dropdown]",c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),f,g;if(c.is(".disabled, :disabled"))return;return f=e(c),g=f.hasClass("open"),d(),g||("ontouchstart"in document.documentElement&&a('<div class="dropdown-backdrop"/>').insertBefore(a(this)).on("click",d),f.toggleClass("open")),c.focus(),!1},keydown:function(c){var d,f,g,h,i,j;if(!/(38|40|27)/.test(c.keyCode))return;d=a(this),c.preventDefault(),c.stopPropagation();if(d.is(".disabled, :disabled"))return;h=e(d),i=h.hasClass("open");if(!i||i&&c.keyCode==27)return c.which==27&&h.find(b).focus(),d.click();f=a("[role=menu] li:not(.divider):visible a",h);if(!f.length)return;j=f.index(f.filter(":focus")),c.keyCode==38&&j>0&&j--,c.keyCode==40&&j<f.length-1&&j++,~j||(j=0),f.eq(j).focus()}};var f=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=f,this},a(document).on("click.dropdown.data-api",d).on("click.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.dropdown.data-api",b,c.prototype.toggle).on("keydown.dropdown.data-api",b+", [role=menu]",c.prototype.keydown)}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-modal",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.options=c,this.$element=a(b).delegate('[data-dismiss="modal"]',"click.dismiss.modal",a.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};b.prototype={constructor:b,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var b=this,c=a.Event("show");this.$element.trigger(c);if(this.isShown||c.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var c=a.support.transition&&b.$element.hasClass("fade");b.$element.parent().length||b.$element.appendTo(document.body),b.$element.show(),c&&b.$element[0].offsetWidth,b.$element.addClass("in").attr("aria-hidden",!1),b.enforceFocus(),c?b.$element.one(a.support.transition.end,function(){b.$element.focus().trigger("shown")}):b.$element.focus().trigger("shown")})},hide:function(b){b&&b.preventDefault();var c=this;b=a.Event("hide"),this.$element.trigger(b);if(!this.isShown||b.isDefaultPrevented())return;this.isShown=!1,this.escape(),a(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),a.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var b=this;a(document).on("focusin.modal",function(a){b.$element[0]!==a.target&&!b.$element.has(a.target).length&&b.$element.focus()})},escape:function(){var a=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(b){b.which==27&&a.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),b.hideModal()},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),b.hideModal()})},hideModal:function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?a.proxy(this.$element[0].focus,this.$element[0]):a.proxy(this.hide,this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!b)return;e?this.$backdrop.one(a.support.transition.end,b):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b):b()):b&&b()}};var c=a.fn.modal;a.fn.modal=function(c){return this.each(function(){var d=a(this),e=d.data("modal"),f=a.extend({},a.fn.modal.defaults,d.data(),typeof c=="object"&&c);e||d.data("modal",e=new b(this,f)),typeof c=="string"?e[c]():f.show&&e.show()})},a.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f).one("hide",function(){c.focus()})})}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-tooltip",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(a,b){this.init("tooltip",a,b)};b.prototype={constructor:b,init:function(b,c,d){var e,f,g,h,i;this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.enabled=!0,g=this.options.trigger.split(" ");for(i=g.length;i--;)h=g[i],h=="click"?this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this)):h!="manual"&&(e=h=="hover"?"mouseenter":"focus",f=h=="hover"?"mouseleave":"blur",this.$element.on(e+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(f+"."+this.type,this.options.selector,a.proxy(this.leave,this)));this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(b){return b=a.extend({},a.fn[this.type].defaults,this.$element.data(),b),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},enter:function(b){var c=a.fn[this.type].defaults,d={},e;this._options&&a.each(this._options,function(a,b){c[a]!=b&&(d[a]=b)}),e=a(b.currentTarget)[this.type](d).data(this.type);if(!e.options.delay||!e.options.delay.show)return e.show();clearTimeout(this.timeout),e.hoverState="in",this.timeout=setTimeout(function(){e.hoverState=="in"&&e.show()},e.options.delay.show)},leave:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!c.options.delay||!c.options.delay.hide)return c.hide();c.hoverState="out",this.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},show:function(){var b,c,d,e,f,g,h=a.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(h);if(h.isDefaultPrevented())return;b=this.tip(),this.setContent(),this.options.animation&&b.addClass("fade"),f=typeof this.options.placement=="function"?this.options.placement.call(this,b[0],this.$element[0]):this.options.placement,b.detach().css({top:0,left:0,display:"block"}),this.options.container?b.appendTo(this.options.container):b.insertAfter(this.$element),c=this.getPosition(),d=b[0].offsetWidth,e=b[0].offsetHeight;switch(f){case"bottom":g={top:c.top+c.height,left:c.left+c.width/2-d/2};break;case"top":g={top:c.top-e,left:c.left+c.width/2-d/2};break;case"left":g={top:c.top+c.height/2-e/2,left:c.left-d};break;case"right":g={top:c.top+c.height/2-e/2,left:c.left+c.width}}this.applyPlacement(g,f),this.$element.trigger("shown")}},applyPlacement:function(a,b){var c=this.tip(),d=c[0].offsetWidth,e=c[0].offsetHeight,f,g,h,i;c.offset(a).addClass(b).addClass("in"),f=c[0].offsetWidth,g=c[0].offsetHeight,b=="top"&&g!=e&&(a.top=a.top+e-g,i=!0),b=="bottom"||b=="top"?(h=0,a.left<0&&(h=a.left*-2,a.left=0,c.offset(a),f=c[0].offsetWidth,g=c[0].offsetHeight),this.replaceArrow(h-d+f,f,"left")):this.replaceArrow(g-e,g,"top"),i&&c.offset(a)},replaceArrow:function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},setContent:function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},hide:function(){function e(){var b=setTimeout(function(){c.off(a.support.transition.end).detach()},500);c.one(a.support.transition.end,function(){clearTimeout(b),c.detach()})}var b=this,c=this.tip(),d=a.Event("hide");this.$element.trigger(d);if(d.isDefaultPrevented())return;return c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?e():c.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var b=this.$element[0];return a.extend({},typeof b.getBoundingClientRect=="function"?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},getTitle:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a},tip:function(){return this.$tip=this.$tip||a(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(b){var c=b?a(b.currentTarget)[this.type](this._options).data(this.type):this;c.tip().hasClass("in")?c.hide():c.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("tooltip"),f=typeof c=="object"&&c;e||d.data("tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-popover",["bootstrap/bootstrap-transition","bootstrap/bootstrap-tooltip"],function(){return function(){!function(a){var b=function(a,b){this.init("popover",a,b)};b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype,{constructor:b,setContent:function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var a,b=this.$element,c=this.options;return a=(typeof c.content=="function"?c.content.call(b[0]):c.content)||b.attr("data-content"),a},tip:function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("popover"),f=typeof c=="object"&&c;e||d.data("popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.defaults=a.extend({},a.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-scrollspy",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){function b(b,c){var d=a.proxy(this.process,this),e=a(b).is("body")?a(window):a(b),f;this.options=a.extend({},a.fn.scrollspy.defaults,c),this.$scrollElement=e.on("scroll.scroll-spy.data-api",d),this.selector=(this.options.target||(f=a(b).attr("href"))&&f.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=a("body"),this.refresh(),this.process()}b.prototype={constructor:b,refresh:function(){var b=this,c;this.offsets=a([]),this.targets=a([]),c=this.$body.find(this.selector).map(function(){var c=a(this),d=c.data("target")||c.attr("href"),e=/^#\w/.test(d)&&a(d);return e&&e.length&&[[e.position().top+(!a.isWindow(b.$scrollElement.get(0))&&b.$scrollElement.scrollTop()),d]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},process:function(){var a=this.$scrollElement.scrollTop()+this.options.offset,b=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,c=b-this.$scrollElement.height(),d=this.offsets,e=this.targets,f=this.activeTarget,g;if(a>=c)return f!=(g=e.last()[0])&&this.activate(g);for(g=d.length;g--;)f!=e[g]&&a>=d[g]&&(!d[g+1]||a<=d[g+1])&&this.activate(e[g])},activate:function(b){var c,d;this.activeTarget=b,a(this.selector).parent(".active").removeClass("active"),d=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',c=a(d).parent("li").addClass("active"),c.parent(".dropdown-menu").length&&(c=c.closest("li.dropdown").addClass("active")),c.trigger("activate")}};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("scrollspy"),f=typeof c=="object"&&c;e||d.data("scrollspy",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.defaults={offset:10},a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-tab",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b){this.element=a(b)};b.prototype={constructor:b,show:function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target"),e,f,g;d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;e=c.find(".active:last a")[0],g=a.Event("show",{relatedTarget:e}),b.trigger(g);if(g.isDefaultPrevented())return;f=a(d),this.activate(b.parent("li"),c),this.activate(f,f.parent(),function(){b.trigger({type:"shown",relatedTarget:e})})},activate:function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g):g(),e.removeClass("in")}};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("tab");e||d.data("tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery)}.call(a),b})}(this),function(a){var b;c("bootstrap/bootstrap-typeahead",["bootstrap/bootstrap-transition"],function(){return function(){!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.typeahead.defaults,c),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=a(this.options.menu),this.shown=!1,this.listen()};b.prototype={constructor:b,select:function(){var a=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(a)).change(),this.hide()},updater:function(a){return a},show:function(){var b=a.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:b.top+b.height,left:b.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(b){var c;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(c=a.isFunction(this.source)?this.source(this.query,a.proxy(this.process,this)):this.source,c?this.process(c):this)},process:function(b){var c=this;return b=a.grep(b,function(a){return c.matcher(a)}),b=this.sorter(b),b.length?this.render(b.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(a){return~a.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(a){var b=[],c=[],d=[],e;while(e=a.shift())e.toLowerCase().indexOf(this.query.toLowerCase())?~e.indexOf(this.query)?c.push(e):d.push(e):b.push(e);return b.concat(c,d)},highlighter:function(a){var b=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return a.replace(new RegExp("("+b+")","ig"),function(a,b){return"<strong>"+b+"</strong>"})},render:function(b){var c=this;return b=a(b).map(function(b,d){return b=a(c.options.item).attr("data-value",d),b.find("a").html(c.highlighter(d)),b[0]}),b.first().addClass("active"),this.$menu.html(b),this},next:function(b){var c=this.$menu.find(".active").removeClass("active"),d=c.next();d.length||(d=a(this.$menu.find("li")[0])),d.addClass("active")},prev:function(a){var b=this.$menu.find(".active").removeClass("active"),c=b.prev();c.length||(c=this.$menu.find("li").last()),c.addClass("active")},listen:function(){this.$element.on("focus",a.proxy(this.focus,this)).on("blur",a.proxy(this.blur,this)).on("keypress",a.proxy(this.keypress,this)).on("keyup",a.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",a.proxy(this.keydown,this)),this.$menu.on("click",a.proxy(this.click,this)).on("mouseenter","li",a.proxy(this.mouseenter,this)).on("mouseleave","li",a.proxy(this.mouseleave,this))},eventSupported:function(a){var b=a in this.$element;return b||(this.$element.setAttribute(a,"return;"),b=typeof this.$element[a]=="function"),b},move:function(a){if(!this.shown)return;switch(a.keyCode){case 9:case 13:case 27:a.preventDefault();break;case 38:a.preventDefault(),this.prev();break;case 40:a.preventDefault(),this.next()}a.stopPropagation()},keydown:function(b){this.suppressKeyPressRepeat=~a.inArray(b.keyCode,[40,38,9,13,27]),this.move(b)},keypress:function(a){if(this.suppressKeyPressRepeat)return;this.move(a)},keyup:function(a){switch(a.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}a.stopPropagation(),a.preventDefault()},focus:function(a){this.focused=!0},blur:function(a){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(a){a.stopPropagation(),a.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(b){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")},mouseleave:function(a){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var c=a.fn.typeahead;a.fn.typeahead=function(c){return this.each(function(){var d=a(this),e=d.data("typeahead"),f=typeof c=="object"&&c;e||d.data("typeahead",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},a.fn.typeahead.Constructor=b,a.fn.typeahead.noConflict=function(){return a.fn.typeahead=c,this},a(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(b){var c=a(this);if(c.data("typeahead"))return;c.typeahead(c.data())})}(window.jQuery)}.call(a),b})}(this),c("fuelux/checkbox",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.checkbox.defaults,c),this.$label=this.$element.parent(),this.$icon=this.$label.find("i"),this.$chk=this.$label.find("input[type=checkbox]"),this.setState(this.$chk),this.$chk.on("change",b.proxy(this.itemchecked,this))};c.prototype={constructor:c,setState:function(a){var b=a.is(":checked"),c=a.is(":disabled");this.$icon.removeClass("checked").removeClass("disabled"),b===!0&&this.$icon.addClass("checked"),c===!0&&this.$icon.addClass("disabled")},enable:function(){this.$chk.attr("disabled",!1),this.$icon.removeClass("disabled")},disable:function(){this.$chk.attr("disabled",!0),this.$icon.addClass("disabled")},toggle:function(){this.$chk.click()},itemchecked:function(a){var c=b(a.target);this.setState(c)}},b.fn.checkbox=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("checkbox"),h=typeof a=="object"&&a;g||f.data("checkbox",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.checkbox.defaults={},b.fn.checkbox.Constructor=c,b(function(){b(window).on("load",function(){b(".checkbox-custom > input[type=checkbox]").each(function(){var a=b(this);if(a.data("checkbox"))return;a.checkbox(a.data())})})})}),c("fuelux/util",["require","jquery"],function(a){function c(a,c){return(a.textContent||a.innerText||b(a).text()||"").toLowerCase()===(c||"").toLowerCase()}var b=a("jquery");b.expr[":"].fuelTextExactCI=b.expr.createPseudo?b.expr.createPseudo(function(a){return function(b){return c(b,a)}}):function(a,b,d){return c(a,d[3])}}),c("fuelux/combobox",["require","jquery","./util"],function(a){var b=a("jquery");a("./util");var c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.combobox.defaults,c),this.$element.on("click","a",b.proxy(this.itemclicked,this)),this.$element.on("change","input",b.proxy(this.inputchanged,this)),this.$input=this.$element.find("input"),this.$button=this.$element.find(".btn"),this.setDefaultSelection()};c.prototype={constructor:c,selectedItem:function(){var a=this.$selectedItem,c={};if(a){var d=this.$selectedItem.text();c=b.extend({text:d},this.$selectedItem.data())}else c={text:this.$input.val()};return c},selectByText:function(a){var b="li:fuelTextExactCI("+a+")";this.selectBySelector(b)},selectByValue:function(a){var b='li[data-value="'+a+'"]';this.selectBySelector(b)},selectByIndex:function(a){var b="li:eq("+a+")";this.selectBySelector(b)},selectBySelector:function(a){var b=this.$element.find(a);typeof b[0]!="undefined"?(this.$selectedItem=b,this.$input.val(this.$selectedItem.text())):this.$selectedItem=null},setDefaultSelection:function(){var a="li[data-selected=true]:first",b=this.$element.find(a);b.length>0&&(this.selectBySelector(a),b.removeData("selected"),b.removeAttr("data-selected"))},enable:function(){this.$input.removeAttr("disabled"),this.$button.removeClass("disabled")},disable:function(){this.$input.attr("disabled",!0),this.$button.addClass("disabled")},itemclicked:function(a){this.$selectedItem=b(a.target).parent(),this.$input.val(this.$selectedItem.text()).trigger("change",{synthetic:!0});var c=this.selectedItem();this.$element.trigger("changed",c),a.preventDefault()},inputchanged:function(a,c){if(c&&c.synthetic)return;var d=b(a.target).val();this.selectByText(d);var e=this.selectedItem();e.text.length===0&&(e={text:d}),this.$element.trigger("changed",e)}},b.fn.combobox=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("combobox"),h=typeof a=="object"&&a;g||f.data("combobox",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.combobox.defaults={},b.fn.combobox.Constructor=c,b(function(){b(window).on("load",function(){b(".combobox").each(function(){var a=b(this);if(a.data("combobox"))return;a.combobox(a.data())})}),b("body").on("mousedown.combobox.data-api",".combobox",function(a){var c=b(this);if(c.data("combobox"))return;c.combobox(c.data())})})}),c("fuelux/datagrid",["require","jquery"],function(a){var b=a("jquery"),c=22,d=function(a,c){this.$element=b(a),this.$thead=this.$element.find("thead"),this.$tfoot=this.$element.find("tfoot"),this.$footer=this.$element.find("tfoot th"),this.$footerchildren=this.$footer.children().show().css("visibility","hidden"),this.$topheader=this.$element.find("thead th"),this.$searchcontrol=this.$element.find(".datagrid-search"),this.$filtercontrol=this.$element.find(".filter"),this.$pagesize=this.$element.find(".grid-pagesize"),this.$pageinput=this.$element.find(".grid-pager input"),this.$pagedropdown=this.$element.find(".grid-pager .dropdown-menu"),this.$prevpagebtn=this.$element.find(".grid-prevpage"),this.$nextpagebtn=this.$element.find(".grid-nextpage"),this.$pageslabel=this.$element.find(".grid-pages"),this.$countlabel=this.$element.find(".grid-count"),this.$startlabel=this.$element.find(".grid-start"),this.$endlabel=this.$element.find(".grid-end"),this.$tbody=b("<tbody>").insertAfter(this.$thead),this.$colheader=b("<tr>").appendTo(this.$thead),this.options=b.extend(!0,{},b.fn.datagrid.defaults,c),this.$pagesize.hasClass("select")?this.options.dataOptions.pageSize=parseInt(this.$pagesize.select("selectedItem").value,10):this.options.dataOptions.pageSize=parseInt(this.$pagesize.val(),10),this.$searchcontrol.length<=0&&(this.$searchcontrol=this.$element.find(".search")),this.columns=this.options.dataSource.columns(),this.$nextpagebtn.on("click",b.proxy(this.next,this)),this.$prevpagebtn.on("click",b.proxy(this.previous,this)),this.$searchcontrol.on("searched cleared",b.proxy(this.searchChanged,this)),this.$filtercontrol.on("changed",b.proxy(this.filterChanged,this)),this.$colheader.on("click","th",b.proxy(this.headerClicked,this)),this.$pagesize.hasClass("select")?this.$pagesize.on("changed",b.proxy(this.pagesizeChanged,this)):this.$pagesize.on("change",b.proxy(this.pagesizeChanged,this)),this.$pageinput.on("change",b.proxy(this.pageChanged,this)),this.renderColumns(),this.options.stretchHeight&&this.initStretchHeight(),this.renderData()};d.prototype={constructor:d,renderColumns:function(){var a=this;this.$footer.attr("colspan",this.columns.length),this.$topheader.attr("colspan",this.columns.length);var c="";b.each(this.columns,function(a,b){c+='<th data-property="'+b.property+'"',b.sortable&&(c+=' class="sortable"'),c+=">"+b.label+"</th>"}),a.$colheader.append(c)},updateColumns:function(a,b){this._updateColumns(this.$colheader,a,b),this.$sizingHeader&&this._updateColumns(this.$sizingHeader,this.$sizingHeader.find("th").eq(a.index()),b)},_updateColumns:function(a,c,d){var e=d==="asc"?"icon-chevron-up":"icon-chevron-down";a.find("i.datagrid-sort").remove(),a.find("th").removeClass("sorted"),b("<i>").addClass(e+" datagrid-sort").appendTo(c),c.addClass("sorted")},updatePageDropdown:function(a){var b="";for(var c=1;c<=a.pages;c++)b+="<li><a>"+c+"</a></li>";this.$pagedropdown.html(b)},updatePageButtons:function(a){a.page===1?this.$prevpagebtn.attr("disabled","disabled"):this.$prevpagebtn.removeAttr("disabled"),a.page===a.pages?this.$nextpagebtn.attr("disabled","disabled"):this.$nextpagebtn.removeAttr("disabled")},renderData:function(){var a=this;this.$tbody.html(this.placeholderRowHTML(this.options.loadingHTML)),this.options.dataSource.data(this.options.dataOptions,function(c){var d=c.count===1?a.options.itemText:a.options.itemsText,e="";a.$footerchildren.css("visibility",function(){return c.count>0?"visible":"hidden"}),a.$pageinput.val(c.page),a.$pageslabel.text(c.pages),a.$countlabel.text(c.count+" "+d),a.$startlabel.text(c.start),a.$endlabel.text(c.end),a.updatePageDropdown(c),a.updatePageButtons(c),b.each(c.data,function(c,d){e+="<tr>",b.each(a.columns,function(a,b){e+="<td>"+d[b.property]+"</td>"}),e+="</tr>"}),e||(e=a.placeholderRowHTML("0 "+a.options.itemsText)),a.$tbody.html(e),a.stretchHeight(),a.$element.trigger("loaded")})},placeholderRowHTML:function(a){return'<tr><td style="text-align:center;padding:20px;border-bottom:none;" colspan="'+this.columns.length+'">'+a+"</td></tr>"},headerClicked:function(a){var c=b(a.target);if(!c.hasClass("sortable"))return;var d=this.options.dataOptions.sortDirection,e=this.options.dataOptions.sortProperty,f=c.data("property");e===f?this.options.dataOptions.sortDirection=d==="asc"?"desc":"asc":(this.options.dataOptions.sortDirection="asc",this.options.dataOptions.sortProperty=f),this.options.dataOptions.pageIndex=0,this.updateColumns(c,this.options.dataOptions.sortDirection),this.renderData()},pagesizeChanged:function(a,c){c?this.options.dataOptions.pageSize=parseInt(c.value,10):this.options.dataOptions.pageSize=parseInt(b(a.target).val(),10),this.options.dataOptions.pageIndex=0,this.renderData()},pageChanged:function(a){var c=parseInt(b(a.target).val(),10);c=isNaN(c)?1:c;var d=this.$pageslabel.text();this.options.dataOptions.pageIndex=c>d?d-1:c-1,this.renderData()},searchChanged:function(a,b){this.options.dataOptions.search=b,this.options.dataOptions.pageIndex=0,this.renderData()},filterChanged:function(a,b){this.options.dataOptions.filter=b,this.options.dataOptions.pageIndex=0,this.renderData()},previous:function(){this.$nextpagebtn.attr("disabled","disabled"),this.$prevpagebtn.attr("disabled","disabled"),this.options.dataOptions.pageIndex--,this.renderData()},next:function(){this.$nextpagebtn.attr("disabled","disabled"),this.$prevpagebtn.attr("disabled","disabled"),this.options.dataOptions.pageIndex++,this.renderData()},reload:function(){this.options.dataOptions.pageIndex=0,this.renderData()},initStretchHeight:function(){this.$gridContainer=this.$element.parent(),this.$element.wrap('<div class="datagrid-stretch-wrapper">'),this.$stretchWrapper=this.$element.parent(),this.$headerTable=b("<table>").attr("class",this.$element.attr("class")),this.$footerTable=this.$headerTable.clone(),this.$headerTable.prependTo(this.$gridContainer).addClass("datagrid-stretch-header"),this.$thead.detach().appendTo(this.$headerTable),this.$sizingHeader=this.$thead.clone(),this.$sizingHeader.find("tr:first").remove(),this.$footerTable.appendTo(this.$gridContainer).addClass("datagrid-stretch-footer"),this.$tfoot.detach().appendTo(this.$footerTable)},stretchHeight:function(){if(!this.$gridContainer)return;this.setColumnWidths();var a=this.$gridContainer.height(),b=this.$headerTable.outerHeight(),c=this.$footerTable.outerHeight(),d=b+c;this.$stretchWrapper.height(a-d)},setColumnWidths:function(){function e(e,f){if(e===d-1)return;var g=b(f),h=a.eq(e),i=h.width();h.hasClass("sorted")&&g.prop("tagName")==="TD"&&(i=i+c),g.width(i)}if(!this.$sizingHeader)return;this.$element.prepend(this.$sizingHeader);var a=this.$sizingHeader.find("th"),d=a.length;this.$colheader.find("th").each(e),this.$tbody.find("tr:first > td").each(e),this.$sizingHeader.detach()}},b.fn.datagrid=function(a){return this.each(function(){var c=b(this),e=c.data("datagrid"),f=typeof a=="object"&&a;e||c.data("datagrid",e=new d(this,f)),typeof a=="string"&&e[a]()})},b.fn.datagrid.defaults={dataOptions:{pageIndex:0,pageSize:10},loadingHTML:'<div class="progress progress-striped active" style="width:50%;margin:auto;"><div class="bar" style="width:100%;"></div></div>',itemsText:"items",itemText:"item"},b.fn.datagrid.Constructor=d}),c("fuelux/pillbox",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.pillbox.defaults,c),this.$element.on("click","li",b.proxy(this.itemclicked,this))};c.prototype={constructor:c,items:function(){return this.$element.find("li").map(function(){var a=b(this);return b.extend({text:a.text()},a.data())}).get()},itemclicked:function(a){b(a.currentTarget).remove(),a.preventDefault()}},b.fn.pillbox=function(a){var d,e=this.each(function(){var e=b(this),f=e.data("pillbox"),g=typeof a=="object"&&a;f||e.data("pillbox",f=new c(this,g)),typeof a=="string"&&(d=f[a]())});return d===undefined?e:d},b.fn.pillbox.defaults={},b.fn.pillbox.Constructor=c,b(function(){b("body").on("mousedown.pillbox.data-api",".pillbox",function(a){var c=b(this);if(c.data("pillbox"))return;c.pillbox(c.data())})})}),c("fuelux/radio",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.radio.defaults,c),this.$label=this.$element.parent(),this.$icon=this.$label.find("i"),this.$radio=this.$label.find("input[type=radio]"),this.groupName=this.$radio.attr("name"),this.setState(this.$radio),this.$radio.on("change",b.proxy(this.itemchecked,this))};c.prototype={constructor:c,setState:function(a,b){var c=a.is(":checked"),d=a.is(":disabled");c===!0&&this.$icon.addClass("checked"),d===!0&&this.$icon.addClass("disabled")},resetGroup:function(){b("input[name="+this.groupName+"]").next().removeClass("checked")},enable:function(){this.$radio.attr("disabled",!1),this.$icon.removeClass("disabled")},disable:function(){this.$radio.attr("disabled",!0),this.$icon.addClass("disabled")},itemchecked:function(a){var c=b(a.target);this.resetGroup(),this.setState(c)}},b.fn.radio=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("radio"),h=typeof a=="object"&&a;g||f.data("radio",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.radio.defaults={},b.fn.radio.Constructor=c,b(function(){b(window).on("load",function(){b(".radio-custom > input[type=radio]").each(function(){var a=b(this);if(a.data("radio"))return;a.radio(a.data())})})})}),c("fuelux/search",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.search.defaults,c),this.$button=this.$element.find("button").on("click",b.proxy(this.buttonclicked,this)),this.$input=this.$element.find("input").on("keydown",b.proxy(this.keypress,this)).on("keyup",b.proxy(this.keypressed,this)),this.$icon=this.$element.find("i"),this.activeSearch=""};c.prototype={constructor:c,search:function(a){this.$icon.attr("class","icon-remove"),this.activeSearch=a,this.$element.trigger("searched",a)},clear:function(){this.$icon.attr("class","icon-search"),this.activeSearch="",this.$input.val(""),this.$element.trigger("cleared")},action:function(){var a=this.$input.val(),b=a===""||a===this.activeSearch;this.activeSearch&&b?this.clear():a&&this.search(a)},buttonclicked:function(a){a.preventDefault();if(b(a.currentTarget).is(".disabled, :disabled"))return;this.action()},keypress:function(a){a.which===13&&a.preventDefault()},keypressed:function(a){var b,c;a.which===13?(a.preventDefault(),this.action()):(b=this.$input.val(),c=b&&b===this.activeSearch,this.$icon.attr("class",c?"icon-remove":"icon-search"))},disable:function(){this.$input.attr("disabled","disabled"),this.$button.addClass("disabled")},enable:function(){this.$input.removeAttr("disabled"),this.$button.removeClass("disabled")}},b.fn.search=function(a){return this.each(function(){var d=b(this),e=d.data("search"),f=typeof a=="object"&&a;e||d.data("search",e=new c(this,f)),typeof a=="string"&&e[a]()})},b.fn.search.defaults={},b.fn.search.Constructor=c,b(function(){b("body").on("mousedown.search.data-api",".search",function(){var a=b(this);if(a.data("search"))return;a.search(a.data())})})}),c("fuelux/spinner",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.spinner.defaults,c),this.$input=this.$element.find(".spinner-input"),this.$element.on("keyup",this.$input,b.proxy(this.change,this)),this.options.hold?(this.$element.on("mousedown",".spinner-up",b.proxy(function(){this.startSpin(!0)},this)),this.$element.on("mouseup",".spinner-up, .spinner-down",b.proxy(this.stopSpin,this)),this.$element.on("mouseout",".spinner-up, .spinner-down",b.proxy(this.stopSpin,this)),this.$element.on("mousedown",".spinner-down",b.proxy(function(){this.startSpin(!1)},this))):(this.$element.on("click",".spinner-up",b.proxy(function(){this.step(!0)},this)),this.$element.on("click",".spinner-down",b.proxy(function(){this.step(!1)},this))),this.switches={count:1,enabled:!0},this.options.speed==="medium"?this.switches.speed=300:this.options.speed==="fast"?this.switches.speed=100:this.switches.speed=500,this.lastValue=null,this.render(),this.options.disabled&&this.disable()};c.prototype={constructor:c,render:function(){this.$input.val(this.options.value),this.$input.attr("maxlength",(this.options.max+"").split("").length)},change:function(){var a=this.$input.val();a/1?this.options.value=a/1:(a=a.replace(/[^0-9]/g,""),this.$input.val(a),this.options.value=a/1),this.triggerChangedEvent()},stopSpin:function(){clearTimeout(this.switches.timeout),this.switches.count=1,this.triggerChangedEvent()},triggerChangedEvent:function(){var a=this.value();if(a===this.lastValue)return;this.lastValue=a,this.$element.trigger("changed",a),this.$element.trigger("change")},startSpin:function(a){if(!this.options.disabled){var c=this.switches.count;c===1?(this.step(a),c=1):c<3?c=1.5:c<8?c=2.5:c=4,this.switches.timeout=setTimeout(b.proxy(function(){this.iterator(a)},this),this.switches.speed/c),this.switches.count++}},iterator:function(a){this.step(a),this.startSpin(a)},step:function(a){var b=this.options.value,c=a?this.options.max:this.options.min;if(a?b<c:b>c){var d=b+(a?1:-1)*this.options.step;(a?d>c:d<c)?this.value(c):this.value(d)}},value:function(a){return!isNaN(parseFloat(a))&&isFinite(a)?(a=parseFloat(a),this.options.value=a,this.$input.val(a),this):this.options.value},disable:function(){this.options.disabled=!0,this.$input.attr("disabled",""),this.$element.find("button").addClass("disabled")},enable:function(){this.options.disabled=!1,this.$input.removeAttr("disabled"),this.$element.find("button").removeClass("disabled")}},b.fn.spinner=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("spinner"),h=typeof a=="object"&&a;g||f.data("spinner",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.spinner.defaults={value:1,min:1,max:999,step:1,hold:!0,speed:"medium",disabled:!1},b.fn.spinner.Constructor=c,b(function(){b("body").on("mousedown.spinner.data-api",".spinner",function(a){var c=b(this);if(c.data("spinner"))return;c.spinner(c.data())})})}),c("fuelux/select",["require","jquery","./util"],function(a){var b=a("jquery");a("./util");var c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.select.defaults,c),this.$element.on("click","a",b.proxy(this.itemclicked,this)),this.$button=this.$element.find(".btn"),this.$label=this.$element.find(".dropdown-label"),this.setDefaultSelection(),c.resize==="auto"&&this.resize()};c.prototype={constructor:c,itemclicked:function(a){this.$selectedItem=b(a.target).parent(),this.$label.text(this.$selectedItem.text());var c=this.selectedItem();this.$element.trigger("changed",c),a.preventDefault()},resize:function(){var a=b("#selectTextSize")[0];a||b("<div/>").attr({id:"selectTextSize"}).appendTo("body");var c=0,d=0;this.$element.find("a").each(function(){var a=b(this),e=a.text(),f=b("#selectTextSize");f.text(e),d=f.outerWidth(),d>c&&(c=d)}),this.$label.width(c)},selectedItem:function(){var a=this.$selectedItem.text();return b.extend({text:a},this.$selectedItem.data())},selectByText:function(a){var b="li a:fuelTextExactCI("+a+")";this.selectBySelector(b)},selectByValue:function(a){var b='li[data-value="'+a+'"]';this.selectBySelector(b)},selectByIndex:function(a){var b="li:eq("+a+")";this.selectBySelector(b)},selectBySelector:function(a){var b=this.$element.find(a);this.$selectedItem=b,this.$label.text(this.$selectedItem.text())},setDefaultSelection:function(){var a="li[data-selected=true]:first",b=this.$element.find(a);b.length===0?this.selectByIndex(0):(this.selectBySelector(a),b.removeData("selected"),b.removeAttr("data-selected"))},enable:function(){this.$button.removeClass("disabled")},disable:function(){this.$button.addClass("disabled")}},b.fn.select=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("select"),h=typeof a=="object"&&a;g||f.data("select",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.select.defaults={},b.fn.select.Constructor=c,b(function(){b(window).on("load",function(){b(".select").each(function(){var a=b(this);if(a.data("select"))return;a.select(a.data())})}),b("body").on("mousedown.select.data-api",".select",function(a){var c=b(this);if(c.data("select"))return;c.select(c.data())})})}),c("fuelux/tree",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){this.$element=b(a),this.options=b.extend({},b.fn.tree.defaults,c),this.$element.on("click",".tree-item",b.proxy(function(a){this.selectItem(a.currentTarget)},this)),this.$element.on("click",".tree-folder-header",b.proxy(function(a){this.selectFolder(a.currentTarget)},this)),this.render()};c.prototype={constructor:c,render:function(){this.populate(this.$element)},populate:function(a){var c=this,d=a.parent().find(".tree-loader:eq(0)");d.show(),this.options.dataSource.data(a.data(),function(e){d.hide(),b.each(e.data,function(b,d){var e;d.type==="folder"?(e=c.$element.find(".tree-folder:eq(0)").clone().show(),e.find(".tree-folder-name").html(d.name),e.find(".tree-loader").html(c.options.loadingHTML),e.find(".tree-folder-header").data(d)):d.type==="item"&&(e=c.$element.find(".tree-item:eq(0)").clone().show(),e.find(".tree-item-name").html(d.name),e.data(d)),a.hasClass("tree-folder-header")?a.parent().find(".tree-folder-content:eq(0)").append(e):a.append(e)}),c.$element.trigger("loaded")})},selectItem:function(a){var c=b(a),d=this.$element.find(".tree-selected"),e=[];this.options.multiSelect?b.each(d,function(a,d){var f=b(d);f[0]!==c[0]&&e.push(b(d).data())}):d[0]!==c[0]&&(d.removeClass("tree-selected").find("i").removeClass("icon-ok").addClass("tree-dot"),e.push(c.data())),c.hasClass("tree-selected")?(c.removeClass("tree-selected"),c.find("i").removeClass("icon-ok").addClass("tree-dot")):(c.addClass("tree-selected"),c.find("i").removeClass("tree-dot").addClass("icon-ok"),this.options.multiSelect&&e.push(c.data())),e.length&&this.$element.trigger("selected",{info:e})},selectFolder:function(a){var c=b(a),d=c.parent();c.find(".icon-folder-close").length?(d.find(".tree-folder-content").children().length?d.find(".tree-folder-content:eq(0)").show():this.populate(c),d.find(".icon-folder-close:eq(0)").removeClass("icon-folder-close").addClass("icon-folder-open"),this.$element.trigger("opened",c.data())):(this.options.cacheItems?d.find(".tree-folder-content:eq(0)").hide():d.find(".tree-folder-content:eq(0)").empty(),d.find(".icon-folder-open:eq(0)").removeClass("icon-folder-open").addClass("icon-folder-close"),this.$element.trigger("closed",c.data()))},selectedItems:function(){var a=this.$element.find(".tree-selected"),c=[];return b.each(a,function(a,d){c.push(b(d).data())}),c}},b.fn.tree=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("tree"),h=typeof a=="object"&&a;g||f.data("tree",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.tree.defaults={multiSelect:!1,loadingHTML:"<div>Loading...</div>",cacheItems:!0},b.fn.tree.Constructor=c}),c("fuelux/wizard",["require","jquery"],function(a){var b=a("jquery"),c=function(a,c){var d;this.$element=b(a),this.options=b.extend({},b.fn.wizard.defaults,c),this.currentStep=1,this.numSteps=this.$element.find("li").length,this.$prevBtn=this.$element.find("button.btn-prev"),this.$nextBtn=this.$element.find("button.btn-next"),d=this.$nextBtn.children().detach(),this.nextText=b.trim(this.$nextBtn.text()),this.$nextBtn.append(d),this.$prevBtn.on("click",b.proxy(this.previous,this)),this.$nextBtn.on("click",b.proxy(this.next,this)),this.$element.on("click","li.complete",b.proxy(this.stepclicked,this))};c.prototype={constructor:c,setState:function(){var a=this.currentStep>1,c=this.currentStep===1,d=this.currentStep===this.numSteps;this.$prevBtn.attr("disabled",c===!0||a===!1);var e=this.$nextBtn.data();if(e&&e.last){this.lastText=e.last;if(typeof this.lastText!="undefined"){var f=d!==!0?this.nextText:this.lastText,g=this.$nextBtn.children().detach();this.$nextBtn.text(f).append(g)}}var h=this.$element.find("li");h.removeClass("active").removeClass("complete"),h.find("span.badge").removeClass("badge-info").removeClass("badge-success");var i="li:lt("+(this.currentStep-1)+")",j=this.$element.find(i);j.addClass("complete"),j.find("span.badge").addClass("badge-success");var k="li:eq("+(this.currentStep-1)+")",l=this.$element.find(k);l.addClass("active"),l.find("span.badge").addClass("badge-info");var m=l.data().target;b(".step-pane").removeClass("active"),b(m).addClass("active"),this.$element.trigger("changed")},stepclicked:function(a){var c=b(a.currentTarget),d=b(".steps li").index(c),e=b.Event("stepclick");this.$element.trigger(e,{step:d+1});if(e.isDefaultPrevented())return;this.currentStep=d+1,this.setState()},previous:function(){var a=this.currentStep>1;if(a){var c=b.Event("change");this.$element.trigger(c,{step:this.currentStep,direction:"previous"});if(c.isDefaultPrevented())return;this.currentStep-=1,this.setState()}},next:function(){var a=this.currentStep+1<=this.numSteps,c=this.currentStep===this.numSteps;if(a){var d=b.Event("change");this.$element.trigger(d,{step:this.currentStep,direction:"next"});if(d.isDefaultPrevented())return;this.currentStep+=1,this.setState()}else c&&this.$element.trigger("finished")},selectedItem:function(a){return{step:this.currentStep}}},b.fn.wizard=function(a,d){var e,f=this.each(function(){var f=b(this),g=f.data("wizard"),h=typeof a=="object"&&a;g||f.data("wizard",g=new c(this,h)),typeof a=="string"&&(e=g[a](d))});return e===undefined?f:e},b.fn.wizard.defaults={},b.fn.wizard.Constructor=c,b(function(){b("body").on("mousedown.wizard.data-api",".wizard",function(){var a=b(this);if(a.data("wizard"))return;a.wizard(a.data())})})}),c("fuelux/all",["require","jquery","bootstrap/bootstrap-affix","bootstrap/bootstrap-alert","bootstrap/bootstrap-button","bootstrap/bootstrap-carousel","bootstrap/bootstrap-collapse","bootstrap/bootstrap-dropdown","bootstrap/bootstrap-modal","bootstrap/bootstrap-popover","bootstrap/bootstrap-scrollspy","bootstrap/bootstrap-tab","bootstrap/bootstrap-tooltip","bootstrap/bootstrap-transition","bootstrap/bootstrap-typeahead","fuelux/checkbox","fuelux/combobox","fuelux/datagrid","fuelux/pillbox","fuelux/radio","fuelux/search","fuelux/spinner","fuelux/select","fuelux/tree","fuelux/wizard"],function(a){a("jquery"),a("bootstrap/bootstrap-affix"),a("bootstrap/bootstrap-alert"),a("bootstrap/bootstrap-button"),a("bootstrap/bootstrap-carousel"),a("bootstrap/bootstrap-collapse"),a("bootstrap/bootstrap-dropdown"),a("bootstrap/bootstrap-modal"),a("bootstrap/bootstrap-popover"),a("bootstrap/bootstrap-scrollspy"),a("bootstrap/bootstrap-tab"),a("bootstrap/bootstrap-tooltip"),a("bootstrap/bootstrap-transition"),a("bootstrap/bootstrap-typeahead"),a("fuelux/checkbox"),a("fuelux/combobox"),a("fuelux/datagrid"),a("fuelux/pillbox"),a("fuelux/radio"),a("fuelux/search"),a("fuelux/spinner"),a("fuelux/select"),a("fuelux/tree"),a("fuelux/wizard")}),c("jquery",[],function(){return jQuery}),c("fuelux/loader",["fuelux/all"],function(){}),b("fuelux/loader")})();
\ No newline at end of file
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/pillbox.js b/opendaylight/web/root/src/main/resources/js/fuelux/pillbox.js
new file mode 100755 (executable)
index 0000000..d61f60b
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Fuel UX Pillbox
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery'],function(require) {
+       
+       var $ = require('jquery');
+
+
+       // PILLBOX CONSTRUCTOR AND PROTOTYPE
+
+       var Pillbox = function (element, options) {
+               this.$element = $(element);
+               this.options = $.extend({}, $.fn.pillbox.defaults, options);
+               this.$element.on('click', 'li', $.proxy(this.itemclicked, this));
+       };
+
+       Pillbox.prototype = {
+               constructor: Pillbox,
+
+               items: function() {
+                       return this.$element.find('li').map(function() {
+                               var $this = $(this);
+                               return $.extend({ text: $this.text() }, $this.data());
+                       }).get();
+               },
+
+               itemclicked: function (e) {
+                       $(e.currentTarget).remove();
+                       e.preventDefault();
+               }
+       };
+
+
+       // PILLBOX PLUGIN DEFINITION
+
+       $.fn.pillbox = function (option) {
+               var methodReturn;
+
+               var $set = this.each(function () {
+                       var $this = $(this);
+                       var data = $this.data('pillbox');
+                       var options = typeof option === 'object' && option;
+
+                       if (!data) $this.data('pillbox', (data = new Pillbox(this, options)));
+                       if (typeof option === 'string') methodReturn = data[option]();
+               });
+
+               return (methodReturn === undefined) ? $set : methodReturn;
+       };
+
+       $.fn.pillbox.defaults = {};
+
+       $.fn.pillbox.Constructor = Pillbox;
+
+
+       // PILLBOX DATA-API
+
+       $(function () {
+               $('body').on('mousedown.pillbox.data-api', '.pillbox', function (e) {
+                       var $this = $(this);
+                       if ($this.data('pillbox')) return;
+                       $this.pillbox($this.data());
+               });
+       });
+       
+});
+
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/radio.js b/opendaylight/web/root/src/main/resources/js/fuelux/radio.js
new file mode 100755 (executable)
index 0000000..a09c07f
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Fuel UX Radio
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery'],function (require) {
+
+       var $ = require('jquery');
+
+
+       // RADIO CONSTRUCTOR AND PROTOTYPE
+
+       var Radio = function (element, options) {
+               this.$element = $(element);
+               this.options = $.extend({}, $.fn.radio.defaults, options);
+
+               // cache elements
+               this.$label = this.$element.parent();
+               this.$icon = this.$label.find('i');
+               this.$radio = this.$label.find('input[type=radio]');
+               this.groupName = this.$radio.attr('name');
+
+               // set default state
+               this.setState(this.$radio);
+
+               // handle events
+               this.$radio.on('change', $.proxy(this.itemchecked, this));
+       };
+
+       Radio.prototype = {
+
+               constructor: Radio,
+
+               setState: function ($radio, resetGroupState) {
+                       var checked = $radio.is(':checked');
+                       var disabled = $radio.is(':disabled');
+
+                       // set state of radio
+                       if (checked === true) {
+                               this.$icon.addClass('checked');
+                       }
+                       if (disabled === true) {
+                               this.$icon.addClass('disabled');
+                       }
+               },
+
+               resetGroup: function () {
+                       // reset all radio buttons in group
+                       $('input[name=' + this.groupName + ']').next().removeClass('checked');
+               },
+
+               enable: function () {
+                       this.$radio.attr('disabled', false);
+                       this.$icon.removeClass('disabled');
+               },
+
+               disable: function () {
+                       this.$radio.attr('disabled', true);
+                       this.$icon.addClass('disabled');
+               },
+
+               itemchecked: function (e) {
+                       var radio = $(e.target);
+
+                       this.resetGroup();
+                       this.setState(radio);
+               }
+       };
+
+
+       // RADIO PLUGIN DEFINITION
+
+       $.fn.radio = function (option, value) {
+               var methodReturn;
+
+               var $set = this.each(function () {
+                       var $this = $(this);
+                       var data = $this.data('radio');
+                       var options = typeof option === 'object' && option;
+
+                       if (!data) $this.data('radio', (data = new Radio(this, options)));
+                       if (typeof option === 'string') methodReturn = data[option](value);
+               });
+
+               return (methodReturn === undefined) ? $set : methodReturn;
+       };
+
+       $.fn.radio.defaults = {};
+
+       $.fn.radio.Constructor = Radio;
+
+
+       // RADIO DATA-API
+
+       $(function () {
+               $(window).on('load', function () {
+                       //$('i.radio').each(function () {
+                       $('.radio-custom > input[type=radio]').each(function () {
+                               var $this = $(this);
+                               if ($this.data('radio')) return;
+                               $this.radio($this.data());
+                       });
+               });
+       });
+
+});
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/search.js b/opendaylight/web/root/src/main/resources/js/fuelux/search.js
new file mode 100755 (executable)
index 0000000..7f6a27b
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Fuel UX Search
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery'],function(require) {
+
+       var $ = require('jquery');
+
+
+       // SEARCH CONSTRUCTOR AND PROTOTYPE
+
+       var Search = function (element, options) {
+               this.$element = $(element);
+               this.options = $.extend({}, $.fn.search.defaults, options);
+
+               this.$button = this.$element.find('button')
+                       .on('click', $.proxy(this.buttonclicked, this));
+
+               this.$input = this.$element.find('input')
+                       .on('keydown', $.proxy(this.keypress, this))
+                       .on('keyup', $.proxy(this.keypressed, this));
+
+               this.$icon = this.$element.find('i');
+               this.activeSearch = '';
+       };
+
+       Search.prototype = {
+
+               constructor: Search,
+
+               search: function (searchText) {
+                       this.$icon.attr('class', 'icon-remove');
+                       this.activeSearch = searchText;
+                       this.$element.trigger('searched', searchText);
+               },
+
+               clear: function () {
+                       this.$icon.attr('class', 'icon-search');
+                       this.activeSearch = '';
+                       this.$input.val('');
+                       this.$element.trigger('cleared');
+               },
+
+               action: function () {
+                       var val = this.$input.val();
+                       var inputEmptyOrUnchanged = val === '' || val === this.activeSearch;
+
+                       if (this.activeSearch && inputEmptyOrUnchanged) {
+                               this.clear();
+                       } else if (val) {
+                               this.search(val);
+                       }
+               },
+
+               buttonclicked: function (e) {
+                       e.preventDefault();
+                       if ($(e.currentTarget).is('.disabled, :disabled')) return;
+                       this.action();
+               },
+
+               keypress: function (e) {
+                       if (e.which === 13) {
+                               e.preventDefault();
+                       }
+               },
+
+               keypressed: function (e) {
+                       var val, inputPresentAndUnchanged;
+
+                       if (e.which === 13) {
+                               e.preventDefault();
+                               this.action();
+                       } else {
+                               val = this.$input.val();
+                               inputPresentAndUnchanged = val && (val === this.activeSearch);
+                               this.$icon.attr('class', inputPresentAndUnchanged ? 'icon-remove' : 'icon-search');
+                       }
+               },
+
+               disable: function () {
+                       this.$input.attr('disabled', 'disabled');
+                       this.$button.addClass('disabled');
+               },
+
+               enable: function () {
+                       this.$input.removeAttr('disabled');
+                       this.$button.removeClass('disabled');
+               }
+
+       };
+
+
+       // SEARCH PLUGIN DEFINITION
+
+       $.fn.search = function (option) {
+               return this.each(function () {
+                       var $this = $(this);
+                       var data = $this.data('search');
+                       var options = typeof option === 'object' && option;
+
+                       if (!data) $this.data('search', (data = new Search(this, options)));
+                       if (typeof option === 'string') data[option]();
+               });
+       };
+
+       $.fn.search.defaults = {};
+
+       $.fn.search.Constructor = Search;
+
+
+       // SEARCH DATA-API
+
+       $(function () {
+               $('body').on('mousedown.search.data-api', '.search', function () {
+                       var $this = $(this);
+                       if ($this.data('search')) return;
+                       $this.search($this.data());
+               });
+       });
+
+});
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/select.js b/opendaylight/web/root/src/main/resources/js/fuelux/select.js
new file mode 100755 (executable)
index 0000000..38e6a60
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Fuel UX Select
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery','./util'],function(require) {
+
+    var $ = require('jquery');
+       require('./util');
+
+    // SELECT CONSTRUCTOR AND PROTOTYPE
+
+    var Select = function (element, options) {
+        this.$element = $(element);
+        this.options = $.extend({}, $.fn.select.defaults, options);
+        this.$element.on('click', 'a', $.proxy(this.itemclicked, this));
+        this.$button = this.$element.find('.btn');
+        this.$label = this.$element.find('.dropdown-label');
+        this.setDefaultSelection();
+
+        if (options.resize === 'auto') {
+            this.resize();
+        }
+    };
+
+    Select.prototype = {
+
+        constructor: Select,
+
+        itemclicked: function (e) {
+            this.$selectedItem = $(e.target).parent();
+            this.$label.text(this.$selectedItem.text());
+
+            // pass object including text and any data-attributes
+            // to onchange event
+            var data = this.selectedItem();
+
+            // trigger changed event
+            this.$element.trigger('changed', data);
+
+            e.preventDefault();
+        },
+
+        resize: function() {
+            var el = $('#selectTextSize')[0];
+
+            // create element if it doesn't exist
+            // used to calculate the length of the longest string
+            if(!el) {
+                $('<div/>').attr({id:'selectTextSize'}).appendTo('body');
+            }
+
+            var width = 0;
+            var newWidth = 0;
+
+            // iterate through each item to find longest string
+            this.$element.find('a').each(function () {
+                var $this = $(this);
+                var txt = $this.text();
+                var $txtSize = $('#selectTextSize');
+                $txtSize.text(txt);
+                newWidth = $txtSize.outerWidth();
+                if(newWidth > width) {
+                    width = newWidth;
+                }
+            });
+
+            this.$label.width(width);
+        },
+
+        selectedItem: function() {
+            var txt = this.$selectedItem.text();
+            return $.extend({ text: txt }, this.$selectedItem.data());
+        },
+
+        selectByText: function(text) {
+            var selector = 'li a:fuelTextExactCI(' + text + ')';
+            this.selectBySelector(selector);
+        },
+
+        selectByValue: function(value) {
+            var selector = 'li[data-value="' + value + '"]';
+            this.selectBySelector(selector);
+        },
+
+        selectByIndex: function(index) {
+            // zero-based index
+            var selector = 'li:eq(' + index + ')';
+            this.selectBySelector(selector);
+        },
+
+        selectBySelector: function(selector) {
+            var item = this.$element.find(selector);
+
+            this.$selectedItem = item;
+            this.$label.text(this.$selectedItem.text());
+        },
+
+        setDefaultSelection: function() {
+            var selector = 'li[data-selected=true]:first';
+            var item = this.$element.find(selector);
+            if(item.length === 0) {
+                // select first item
+                this.selectByIndex(0);
+            }
+            else {
+                // select by data-attribute
+                this.selectBySelector(selector);
+                item.removeData('selected');
+                item.removeAttr('data-selected');
+            }
+        },
+
+        enable: function() {
+            this.$button.removeClass('disabled');
+        },
+
+        disable: function() {
+            this.$button.addClass('disabled');
+        }
+
+    };
+
+
+    // SELECT PLUGIN DEFINITION
+
+    $.fn.select = function (option,value) {
+        var methodReturn;
+
+        var $set = this.each(function () {
+            var $this = $(this);
+            var data = $this.data('select');
+            var options = typeof option === 'object' && option;
+
+            if (!data) $this.data('select', (data = new Select(this, options)));
+            if (typeof option === 'string') methodReturn = data[option](value);
+        });
+
+        return (methodReturn === undefined) ? $set : methodReturn;
+    };
+
+    $.fn.select.defaults = {};
+
+    $.fn.select.Constructor = Select;
+
+
+    // SELECT DATA-API
+
+    $(function () {
+
+        $(window).on('load', function () {
+            $('.select').each(function () {
+                var $this = $(this);
+                if ($this.data('select')) return;
+                $this.select($this.data());
+            });
+        });
+
+        $('body').on('mousedown.select.data-api', '.select', function (e) {
+            var $this = $(this);
+            if ($this.data('select')) return;
+            $this.select($this.data());
+        });
+    });
+
+});
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/spinner.js b/opendaylight/web/root/src/main/resources/js/fuelux/spinner.js
new file mode 100755 (executable)
index 0000000..97720ee
--- /dev/null
@@ -0,0 +1,201 @@
+/*\r
+ * Fuel UX Spinner\r
+ * https://github.com/ExactTarget/fuelux\r
+ *\r
+ * Copyright (c) 2012 ExactTarget\r
+ * Licensed under the MIT license.\r
+ */\r
+\r
+define(['require','jquery'],function(require) {\r
+\r
+       var $ = require('jquery');\r
+\r
+\r
+       // SPINNER CONSTRUCTOR AND PROTOTYPE\r
+\r
+       var Spinner = function (element, options) {\r
+               this.$element = $(element);\r
+               this.options = $.extend({}, $.fn.spinner.defaults, options);\r
+               this.$input = this.$element.find('.spinner-input');\r
+               this.$element.on('keyup', this.$input, $.proxy(this.change, this));\r
+\r
+               if (this.options.hold) {\r
+                       this.$element.on('mousedown', '.spinner-up', $.proxy(function() { this.startSpin(true); } , this));\r
+                       this.$element.on('mouseup', '.spinner-up, .spinner-down', $.proxy(this.stopSpin, this));\r
+                       this.$element.on('mouseout', '.spinner-up, .spinner-down', $.proxy(this.stopSpin, this));\r
+                       this.$element.on('mousedown', '.spinner-down', $.proxy(function() {this.startSpin(false);} , this));\r
+               } else {\r
+                       this.$element.on('click', '.spinner-up', $.proxy(function() { this.step(true); } , this));\r
+                       this.$element.on('click', '.spinner-down', $.proxy(function() { this.step(false); }, this));\r
+               }\r
+\r
+               this.switches = {\r
+                       count: 1,\r
+                       enabled: true\r
+               };\r
+\r
+               if (this.options.speed === 'medium') {\r
+                       this.switches.speed = 300;\r
+               } else if (this.options.speed === 'fast') {\r
+                       this.switches.speed = 100;\r
+               } else {\r
+                       this.switches.speed = 500;\r
+               }\r
+\r
+               this.lastValue = null;\r
+\r
+               this.render();\r
+\r
+               if (this.options.disabled) {\r
+                       this.disable();\r
+               }\r
+       };\r
+\r
+       Spinner.prototype = {\r
+               constructor: Spinner,\r
+\r
+               render: function () {\r
+                       this.$input.val(this.options.value);\r
+                       this.$input.attr('maxlength',(this.options.max + '').split('').length);\r
+               },\r
+\r
+               change: function () {\r
+                       var newVal = this.$input.val();\r
+\r
+                       if(newVal/1){\r
+                               this.options.value = newVal/1;\r
+                       }else{\r
+                               newVal = newVal.replace(/[^0-9]/g,'');\r
+                               this.$input.val(newVal);\r
+                               this.options.value = newVal/1;\r
+                       }\r
+\r
+                       this.triggerChangedEvent();\r
+               },\r
+\r
+               stopSpin: function () {\r
+                       clearTimeout(this.switches.timeout);\r
+                       this.switches.count = 1;\r
+                       this.triggerChangedEvent();\r
+               },\r
+\r
+               triggerChangedEvent: function () {\r
+                       var currentValue = this.value();\r
+                       if (currentValue === this.lastValue) return;\r
+\r
+                       this.lastValue = currentValue;\r
+\r
+                       // Primary changed event\r
+                       this.$element.trigger('changed', currentValue);\r
+\r
+                       // Undocumented, kept for backward compatibility\r
+                       this.$element.trigger('change');\r
+               },\r
+\r
+               startSpin: function (type) {\r
+\r
+                       if (!this.options.disabled) {\r
+                               var divisor = this.switches.count;\r
+\r
+                               if (divisor === 1) {\r
+                                       this.step(type);\r
+                                       divisor = 1;\r
+                               } else if (divisor < 3){\r
+                                       divisor = 1.5;\r
+                               } else if (divisor < 8){\r
+                                       divisor = 2.5;\r
+                               } else {\r
+                                       divisor = 4;\r
+                               }\r
+\r
+                               this.switches.timeout = setTimeout($.proxy(function() {this.iterator(type);} ,this),this.switches.speed/divisor);\r
+                               this.switches.count++;\r
+                       }\r
+               },\r
+\r
+               iterator: function (type) {\r
+                       this.step(type);\r
+                       this.startSpin(type);\r
+               },\r
+\r
+               step: function (dir) {\r
+                       var curValue = this.options.value;\r
+                       var limValue = dir ? this.options.max : this.options.min;\r
+\r
+                       if ((dir ? curValue < limValue : curValue > limValue)) {\r
+                               var newVal = curValue + (dir ? 1 : -1) * this.options.step;\r
+\r
+                               if (dir ? newVal > limValue : newVal < limValue) {\r
+                                       this.value(limValue);\r
+                               } else {\r
+                                       this.value(newVal);\r
+                               }\r
+                       }\r
+               },\r
+\r
+               value: function (value) {\r
+                       if (!isNaN(parseFloat(value)) && isFinite(value)) {\r
+                               value = parseFloat(value);\r
+                               this.options.value = value;\r
+                               this.$input.val(value);\r
+                               return this;\r
+                       } else {\r
+                               return this.options.value;\r
+                       }\r
+               },\r
+\r
+               disable: function () {\r
+                       this.options.disabled = true;\r
+                       this.$input.attr('disabled','');\r
+                       this.$element.find('button').addClass('disabled');\r
+               },\r
+\r
+               enable: function () {\r
+                       this.options.disabled = false;\r
+                       this.$input.removeAttr("disabled");\r
+                       this.$element.find('button').removeClass('disabled');\r
+               }\r
+       };\r
+\r
+\r
+       // SPINNER PLUGIN DEFINITION\r
+\r
+       $.fn.spinner = function (option,value) {\r
+               var methodReturn;\r
+\r
+               var $set = this.each(function () {\r
+                       var $this = $(this);\r
+                       var data = $this.data('spinner');\r
+                       var options = typeof option === 'object' && option;\r
+\r
+                       if (!data) $this.data('spinner', (data = new Spinner(this, options)));\r
+                       if (typeof option === 'string') methodReturn = data[option](value);\r
+               });\r
+\r
+               return (methodReturn === undefined) ? $set : methodReturn;\r
+       };\r
+\r
+       $.fn.spinner.defaults = {\r
+               value: 1,\r
+               min: 1,\r
+               max: 999,\r
+               step: 1,\r
+               hold: true,\r
+               speed: 'medium',\r
+               disabled: false\r
+       };\r
+\r
+       $.fn.spinner.Constructor = Spinner;\r
+\r
+\r
+       // SPINNER DATA-API\r
+\r
+       $(function () {\r
+               $('body').on('mousedown.spinner.data-api', '.spinner', function (e) {\r
+                       var $this = $(this);\r
+                       if ($this.data('spinner')) return;\r
+                       $this.spinner($this.data());\r
+               });\r
+       });\r
+\r
+});\r
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/tree.js b/opendaylight/web/root/src/main/resources/js/fuelux/tree.js
new file mode 100755 (executable)
index 0000000..b243719
--- /dev/null
@@ -0,0 +1,169 @@
+/*\r
+ * Fuel UX Tree\r
+ * https://github.com/ExactTarget/fuelux\r
+ *\r
+ * Copyright (c) 2012 ExactTarget\r
+ * Licensed under the MIT license.\r
+ */\r
+\r
+define(['require','jquery'],function(require) {\r
+\r
+       var $ = require('jquery');\r
+\r
+\r
+       // TREE CONSTRUCTOR AND PROTOTYPE\r
+\r
+       var Tree = function (element, options) {\r
+               this.$element = $(element);\r
+               this.options = $.extend({}, $.fn.tree.defaults, options);\r
+\r
+               this.$element.on('click', '.tree-item', $.proxy( function(ev) { this.selectItem(ev.currentTarget); } ,this));\r
+               this.$element.on('click', '.tree-folder-header', $.proxy( function(ev) { this.selectFolder(ev.currentTarget); }, this));\r
+\r
+               this.render();\r
+       };\r
+\r
+       Tree.prototype = {\r
+               constructor: Tree,\r
+\r
+               render: function () {\r
+                       this.populate(this.$element);\r
+               },\r
+\r
+               populate: function ($el) {\r
+                       var self = this;\r
+                       var loader = $el.parent().find('.tree-loader:eq(0)');\r
+\r
+                       loader.show();\r
+                       this.options.dataSource.data($el.data(), function (items) {\r
+                               loader.hide();\r
+\r
+                               $.each( items.data, function(index, value) {\r
+                                       var $entity;\r
+\r
+                                       if(value.type === "folder") {\r
+                                               $entity = self.$element.find('.tree-folder:eq(0)').clone().show();\r
+                                               $entity.find('.tree-folder-name').html(value.name);\r
+                                               $entity.find('.tree-loader').html(self.options.loadingHTML);\r
+                                               $entity.find('.tree-folder-header').data(value);\r
+                                       } else if (value.type === "item") {\r
+                                               $entity = self.$element.find('.tree-item:eq(0)').clone().show();\r
+                                               $entity.find('.tree-item-name').html(value.name);\r
+                                               $entity.data(value);\r
+                                       }\r
+\r
+                                       if($el.hasClass('tree-folder-header')) {\r
+                                               $el.parent().find('.tree-folder-content:eq(0)').append($entity);\r
+                                       } else {\r
+                                               $el.append($entity);\r
+                                       }\r
+                               });\r
+\r
+                               self.$element.trigger('loaded');\r
+                       });\r
+               },\r
+\r
+               selectItem: function (el) {\r
+                       var $el = $(el);\r
+                       var $all = this.$element.find('.tree-selected');\r
+                       var data = [];\r
+\r
+                       if (this.options.multiSelect) {\r
+                               $.each($all, function(index, value) {\r
+                                       var $val = $(value);\r
+                                       if($val[0] !== $el[0]) {\r
+                                               data.push( $(value).data() );\r
+                                       }\r
+                               });\r
+                       } else if ($all[0] !== $el[0]) {\r
+                               $all.removeClass('tree-selected')\r
+                                       .find('i').removeClass('icon-ok').addClass('tree-dot');\r
+                               data.push($el.data());\r
+                       }\r
+\r
+                       if($el.hasClass('tree-selected')) {\r
+                               $el.removeClass('tree-selected');\r
+                               $el.find('i').removeClass('icon-ok').addClass('tree-dot');\r
+                       } else {\r
+                               $el.addClass ('tree-selected');\r
+                               $el.find('i').removeClass('tree-dot').addClass('icon-ok');\r
+                               if (this.options.multiSelect) {\r
+                                       data.push( $el.data() );\r
+                               }\r
+                       }\r
+\r
+                       if(data.length) {\r
+                               this.$element.trigger('selected', {info: data});\r
+                       }\r
+\r
+               },\r
+\r
+               selectFolder: function (el) {\r
+                       var $el = $(el);\r
+                       var $par = $el.parent();\r
+\r
+                       if($el.find('.icon-folder-close').length) {\r
+                               if ($par.find('.tree-folder-content').children().length) {\r
+                                       $par.find('.tree-folder-content:eq(0)').show();\r
+                               } else {\r
+                                       this.populate( $el );\r
+                               }\r
+\r
+                               $par.find('.icon-folder-close:eq(0)')\r
+                                       .removeClass('icon-folder-close')\r
+                                       .addClass('icon-folder-open');\r
+\r
+                               this.$element.trigger('opened', $el.data());\r
+                       } else {\r
+                               if(this.options.cacheItems) {\r
+                                       $par.find('.tree-folder-content:eq(0)').hide();\r
+                               } else {\r
+                                       $par.find('.tree-folder-content:eq(0)').empty();\r
+                               }\r
+\r
+                               $par.find('.icon-folder-open:eq(0)')\r
+                                       .removeClass('icon-folder-open')\r
+                                       .addClass('icon-folder-close');\r
+\r
+                               this.$element.trigger('closed', $el.data());\r
+                       }\r
+               },\r
+\r
+               selectedItems: function () {\r
+                       var $sel = this.$element.find('.tree-selected');\r
+                       var data = [];\r
+\r
+                       $.each($sel, function (index, value) {\r
+                               data.push($(value).data());\r
+                       });\r
+                       return data;\r
+               }\r
+       };\r
+\r
+\r
+       // TREE PLUGIN DEFINITION\r
+\r
+       $.fn.tree = function (option, value) {\r
+               var methodReturn;\r
+\r
+               var $set = this.each(function () {\r
+                       var $this = $(this);\r
+                       var data = $this.data('tree');\r
+                       var options = typeof option === 'object' && option;\r
+\r
+                       if (!data) $this.data('tree', (data = new Tree(this, options)));\r
+                       if (typeof option === 'string') methodReturn = data[option](value);\r
+               });\r
+\r
+               return (methodReturn === undefined) ? $set : methodReturn;\r
+       };\r
+\r
+       $.fn.tree.defaults = {\r
+               multiSelect: false,\r
+               loadingHTML: '<div>Loading...</div>',\r
+               cacheItems: true\r
+       };\r
+\r
+       $.fn.tree.Constructor = Tree;\r
+\r
+});\r
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/util.js b/opendaylight/web/root/src/main/resources/js/fuelux/util.js
new file mode 100755 (executable)
index 0000000..469e9db
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Fuel UX Utilities
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery'],function (require) {
+
+       var $ = require('jquery');
+
+       // custom case-insensitive match expression
+       function fuelTextExactCI(elem, text) {
+               return (elem.textContent || elem.innerText || $(elem).text() || '').toLowerCase() === (text || '').toLowerCase();
+       }
+
+       $.expr[':'].fuelTextExactCI = $.expr.createPseudo ?
+               $.expr.createPseudo(function (text) {
+                       return function (elem) {
+                               return fuelTextExactCI(elem, text);
+                       };
+               }) :
+               function (elem, i, match) {
+                       return fuelTextExactCI(elem, match[3]);
+               };
+
+});
\ No newline at end of file
diff --git a/opendaylight/web/root/src/main/resources/js/fuelux/wizard.js b/opendaylight/web/root/src/main/resources/js/fuelux/wizard.js
new file mode 100755 (executable)
index 0000000..31b9d80
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Fuel UX Wizard
+ * https://github.com/ExactTarget/fuelux
+ *
+ * Copyright (c) 2012 ExactTarget
+ * Licensed under the MIT license.
+ */
+
+define(['require','jquery'],function (require) {
+
+       var $ = require('jquery');
+
+
+       // WIZARD CONSTRUCTOR AND PROTOTYPE
+
+       var Wizard = function (element, options) {
+               var kids;
+
+               this.$element = $(element);
+               this.options = $.extend({}, $.fn.wizard.defaults, options);
+               this.currentStep = 1;
+               this.numSteps = this.$element.find('li').length;
+               this.$prevBtn = this.$element.find('button.btn-prev');
+               this.$nextBtn = this.$element.find('button.btn-next');
+
+               kids = this.$nextBtn.children().detach();
+               this.nextText = $.trim(this.$nextBtn.text());
+               this.$nextBtn.append(kids);
+
+               // handle events
+               this.$prevBtn.on('click', $.proxy(this.previous, this));
+               this.$nextBtn.on('click', $.proxy(this.next, this));
+               this.$element.on('click', 'li.complete', $.proxy(this.stepclicked, this));
+       };
+
+       Wizard.prototype = {
+
+               constructor: Wizard,
+
+               setState: function () {
+                       var canMovePrev = (this.currentStep > 1);
+                       var firstStep = (this.currentStep === 1);
+                       var lastStep = (this.currentStep === this.numSteps);
+
+                       // disable buttons based on current step
+                       this.$prevBtn.attr('disabled', (firstStep === true || canMovePrev === false));
+
+                       // change button text of last step, if specified
+                       var data = this.$nextBtn.data();
+                       if (data && data.last) {
+                               this.lastText = data.last;
+                               if (typeof this.lastText !== 'undefined') {
+                                       // replace text
+                                       var text = (lastStep !== true) ? this.nextText : this.lastText;
+                                       var kids = this.$nextBtn.children().detach();
+                                       this.$nextBtn.text(text).append(kids);
+                               }
+                       }
+
+                       // reset classes for all steps
+                       var $steps = this.$element.find('li');
+                       $steps.removeClass('active').removeClass('complete');
+                       $steps.find('span.badge').removeClass('badge-info').removeClass('badge-success');
+
+                       // set class for all previous steps
+                       var prevSelector = 'li:lt(' + (this.currentStep - 1) + ')';
+                       var $prevSteps = this.$element.find(prevSelector);
+                       $prevSteps.addClass('complete');
+                       $prevSteps.find('span.badge').addClass('badge-success');
+
+                       // set class for current step
+                       var currentSelector = 'li:eq(' + (this.currentStep - 1) + ')';
+                       var $currentStep = this.$element.find(currentSelector);
+                       $currentStep.addClass('active');
+                       $currentStep.find('span.badge').addClass('badge-info');
+
+                       // set display of target element
+                       var target = $currentStep.data().target;
+                       $('.step-pane').removeClass('active');
+                       $(target).addClass('active');
+
+                       this.$element.trigger('changed');
+               },
+
+               stepclicked: function (e) {
+                       var li = $(e.currentTarget);
+
+                       var index = $('.steps li').index(li);
+
+                       var evt = $.Event('stepclick');
+                       this.$element.trigger(evt, {step: index + 1});
+                       if (evt.isDefaultPrevented()) return;
+
+                       this.currentStep = (index + 1);
+                       this.setState();
+               },
+
+               previous: function () {
+                       var canMovePrev = (this.currentStep > 1);
+                       if (canMovePrev) {
+                               var e = $.Event('change');
+                               this.$element.trigger(e, {step: this.currentStep, direction: 'previous'});
+                               if (e.isDefaultPrevented()) return;
+
+                               this.currentStep -= 1;
+                               this.setState();
+                       }
+               },
+
+               next: function () {
+                       var canMoveNext = (this.currentStep + 1 <= this.numSteps);
+                       var lastStep = (this.currentStep === this.numSteps);
+
+                       if (canMoveNext) {
+                               var e = $.Event('change');
+                               this.$element.trigger(e, {step: this.currentStep, direction: 'next'});
+
+                               if (e.isDefaultPrevented()) return;
+
+                               this.currentStep += 1;
+                               this.setState();
+                       }
+                       else if (lastStep) {
+                               this.$element.trigger('finished');
+                       }
+               },
+
+               selectedItem: function (val) {
+                       return {
+                               step: this.currentStep
+                       };
+               }
+       };
+
+
+       // WIZARD PLUGIN DEFINITION
+
+       $.fn.wizard = function (option, value) {
+               var methodReturn;
+
+               var $set = this.each(function () {
+                       var $this = $(this);
+                       var data = $this.data('wizard');
+                       var options = typeof option === 'object' && option;
+
+                       if (!data) $this.data('wizard', (data = new Wizard(this, options)));
+                       if (typeof option === 'string') methodReturn = data[option](value);
+               });
+
+               return (methodReturn === undefined) ? $set : methodReturn;
+       };
+
+       $.fn.wizard.defaults = {};
+
+       $.fn.wizard.Constructor = Wizard;
+
+
+       // WIZARD DATA-API
+
+       $(function () {
+               $('body').on('mousedown.wizard.data-api', '.wizard', function () {
+                       var $this = $(this);
+                       if ($this.data('wizard')) return;
+                       $this.wizard($this.data());
+               });
+       });
+
+});
index 6b73668ab885d3c351e2bfcf15622710555381d8..9c7126274579b0609370ccec088b40343cde158f 100644 (file)
@@ -67,6 +67,64 @@ one.lib.dashlet = {
             return $buttonGroup;
         }
     },
+    datagrid: {
+        /*
+         * The init function returns HTML markup for the datagrid per the options provided. Each consumer 
+         * of the datagrid must first call init and then provide the datasource for the grid.   
+         * id: this is the id of the table
+         * options: {
+         * searchable: true/false,
+         * pagination: turned off for now,
+         * flexibleRowsPerPage: turned off
+         * }
+         * classes : String containing bootstrap related classes. For ex: "table-striped table-condensed"
+         * The classes "table", "table-bordered" and "datagrid" will be added by default
+         */
+        init: function(id, options, classes) {
+            var $fuelGridContainerDiv = $(document.createElement("div"));
+            $fuelGridContainerDiv.addClass("fuelux");
+            $table = $(document.createElement("table"));
+            $table.attr("id", id);
+            $table.addClass("table table-bordered datagrid");
+            $table.addClass(classes);
+            // create datagrid header
+            $thead = $(document.createElement("thead"));
+            $headertr = $(document.createElement("tr"));
+            $headerth = $(document.createElement("th"));
+            // create datagrid footer
+            $tfoot = $(document.createElement("tfoot"));
+            $footertr = $(document.createElement("tr"));
+            $footerth = $(document.createElement("th"));
+            if(options.searchable == true) {
+                $headerth.append(one.lib.dashlet.datagrid._searchable());
+            }
+            if(options.flexibleRowsPerPage == true) {
+                $footerth.append(one.lib.dashlet.datagrid._rowsPerPage());
+            }
+            if(options.pagination == true) {
+                $footerth.append(one.lib.dashlet.datagrid._pagination());
+            }
+            $headertr.append($headerth);
+            $thead.append($headertr);
+            $footertr.append($footerth);
+            $tfoot.append($footertr);
+            $table.append($thead).append($tfoot);
+            $fuelGridContainerDiv.append($table);
+            return $fuelGridContainerDiv;
+        },
+        _searchable: function() {
+            var searchHTML = "<div class='datagrid-header-left'><div class='input-append search datagrid-search'> <input type='text' class='input-medium' placeholder='Search'><button type='button' class='btn'><i class='icon-search'></i></button></div></div>";
+            return searchHTML;
+        },
+        _pagination: function() {
+            var html = '<div class="datagrid-footer-right" style="display:none;"><div class="grid-pager"><button type="button" class="btn grid-prevpage"><i class="icon-chevron-left"></i></button><span>Page</span> <div style="display:inline-block;"><input type="text" name="pagenumber" style="width:25px;margin-bottom:-10px;vertical-align:middle;margin-right:5px;"></div><span>of <span class="grid-pages"></span></span><button type="button" class="btn grid-nextpage"><i class="icon-chevron-right"></i></button></div></div>';
+            return html;
+        },
+        _rowsPerPage: function() {
+            var html = '<div class="datagrid-footer-left" style="display:none;"><div class="grid-controls"><span><span class="grid-start"></span>-<span class="grid-end"></span> of <span class="grid-count"></span></span><div class="select grid-pagesize" data-resize="auto" style="visibility:hidden;"><button type="button" data-toggle="dropdown" class="btn dropdown-toggle"><span class="dropdown-label"></span><span class="caret"></span></button><ul class="dropdown-menu"><li data-value="5" data-selected="true"><a href="#">5</a></li><li data-value="10"><a href="#">10</a></li><li data-value="20"><a href="#">20</a></li><li data-value="50"><a href="#">50</a></li><li data-value="100"><a href="#">100</a></li></ul></div><span style="display:none;">Per Page</span></div></div>';
+            return html;
+        }
+    },
     table : {
         table : function(classes, id) {
             var $table = $(document.createElement('table'));
diff --git a/opendaylight/web/root/src/main/resources/js/underscore-min.js b/opendaylight/web/root/src/main/resources/js/underscore-min.js
new file mode 100644 (file)
index 0000000..459f691
--- /dev/null
@@ -0,0 +1,32 @@
+// Underscore.js 1.3.3
+// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+(function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
+c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break;
+g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,
+c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===o)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===o)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.map===z)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(A&&
+a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,
+c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,
+a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
+function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&
+(e={value:a,computed:b})});return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){d=Math.floor(Math.random()*(f+1));b[f]=b[d];b[d]=a});return b};b.sortBy=function(a,c,d){var e=b.isFunction(c)?c:function(a){return a[c]};return b.pluck(b.map(a,function(a,b,c){return{value:a,criteria:e.call(d,a,b,c)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c===void 0?1:d===void 0?-1:c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};
+j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?i.call(a):a.toArray&&b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=function(a){return b.isArray(a)?a.length:b.keys(a).length};b.first=b.head=b.take=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,
+0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,
+e=[];a.length<3&&(c=true);b.reduce(d,function(d,g,h){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[h])}return d},[]);return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=
+i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(q&&a.indexOf===q)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(F&&a.lastIndexOf===F)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){if(arguments.length<=
+1){b=a||0;a=0}for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+d}return g};var H=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));H.prototype=a.prototype;var b=new H,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=
+i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(null,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i,j=b.debounce(function(){h=
+g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);j()},c));g?h=true:i=a.apply(d,e);j();g=true;return i}};b.debounce=function(a,b,d){var e;return function(){var f=this,g=arguments;d&&!e&&a.apply(f,g);clearTimeout(e);e=setTimeout(function(){e=null;d||a.apply(f,g)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));
+return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&
+c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=
+function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"};
+b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,
+b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId=
+function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape||
+u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};
+b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d,
+this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
\ No newline at end of file
index 87e07f57df22d48ddff3ceb2908a4fc8a4d39d9b..3f0dc9e81231b50dc098011f20dd53f11ffdcfeb 100644 (file)
@@ -1,4 +1,3 @@
-
 /* 
  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved. 
  * 
@@ -18,12 +17,12 @@ one.f.dashlet = {
         name : 'Existing Nodes'
     },
     uptime: {
-       id: 'uptime',
-       name: 'Uptime'
+        id: 'uptime',
+        name: 'Uptime'
     },
     flowsOrPorts: {
-       id: "flowsOrPorts",
-       name: "Statistics"
+        id: "flowsOrPorts",
+        name: "Statistics"
     }
 };
 
@@ -63,234 +62,484 @@ $(one.f.menu.right.bottom).each(function(index, value) {
 
 /**Troubleshoot modules*/
 one.f.troubleshooting = {
-       rootUrl: "/controller/web/troubleshoot",
-       rightBottomDashlet: { 
-               get: function() {
-                       var $rightBottomDashlet = $("#right-bottom").find(".dashlet");
-                       return $rightBottomDashlet;
-               },
-               setDashletHeader: function(label) {
-                       $("#right-bottom li a")[0].innerHTML = label; 
-               }
-       },
-       createTable: function(columnNames, body) {
-               var tableAttributes = ["table-striped", "table-bordered", "table-condensed"];
-               var $table = one.lib.dashlet.table.table(tableAttributes);
-               var tableHeaders = columnNames;
-               var $thead = one.lib.dashlet.table.header(tableHeaders);
-               var $tbody = one.lib.dashlet.table.body(body, tableHeaders);
-               $table.append($thead)
-                       .append($tbody);
-               return $table;
-       }
+    rootUrl: "/controller/web/troubleshoot",
+    rightBottomDashlet: { 
+        get: function() {
+            var $rightBottomDashlet = $("#right-bottom").find(".dashlet");
+            return $rightBottomDashlet;
+        },
+        setDashletHeader: function(label) {
+            $("#right-bottom li a")[0].innerHTML = label; 
+        }
+    },
+    createTable: function(columnNames, body) {
+        var tableAttributes = ["table-striped", "table-bordered", "table-condensed"];
+        var $table = one.lib.dashlet.table.table(tableAttributes);
+        var tableHeaders = columnNames;
+        var $thead = one.lib.dashlet.table.header(tableHeaders);
+        var $tbody = one.lib.dashlet.table.body(body, tableHeaders);
+        $table.append($thead)
+            .append($tbody);
+        return $table;
+    }
 };
 
 one.f.troubleshooting.existingNodes = {
-               id: {
-                       popout: "one_f_troubleshooting_existingNodes_id_popout",
-                       modal: "one_f_troubleshooting_existingNodes_id_modal"
-               },
-               // TODO: Make these values configurable.
-               autoRefreshInterval: {
-                       flows: 10000,
-                       ports: 10000,
-                       refreshRateInterval: 5000
-               },
-               load: {
-                       main: function($dashlet) {
-                               one.lib.dashlet.empty($dashlet);
-                               $dashlet.append(one.lib.dashlet.header(one.f.dashlet.existingNodes.name));
-                               
-                               // TODO(l): Add a generic auto expand function to one.lib and replace custom height setting.
-                               //$('#left-top').height('100%');
-                               one.f.troubleshooting.existingNodes.ajax(one.f.troubleshooting.rootUrl + "/existingNodes" , function(content) {
-                                       var body = one.f.troubleshooting.existingNodes.data.existingNodes(content);
-                                       var $table = one.f.troubleshooting.createTable(content.columnNames, body);
-                                       $dashlet.append($table);
-                               });
-                       },
-                       flows: function(nodeId) {
-                               try {
-                                       clearTimeout(one.f.troubleshooting.existingNodes.registry.refreshTimer);
-                                       $.getJSON(one.main.constants.address.prefix + "/troubleshoot/flowStats?nodeId=" + nodeId, function(content) {
-                                               var body = one.f.troubleshooting.existingNodes.data.flows(content);
-                                               var $table = one.f.troubleshooting.createTable(content.columnNames, body);
-                                               $rightBottomDashlet = one.f.troubleshooting.rightBottomDashlet.get();
-                                               one.f.troubleshooting.rightBottomDashlet.setDashletHeader("Flows");
-                                               one.lib.dashlet.empty($rightBottomDashlet);
-                                               $rightBottomDashlet.append(one.lib.dashlet.header("Flow Details"));
-                                               $rightBottomDashlet.append($table);
-                                               var numberOfFlows = content.nodeData.length;
-                                               var refreshRate = one.f.troubleshooting.existingNodes.autoRefreshInterval.flows;
-                                               if (numberOfFlows > 0) {
-                                                       refreshRate += Math.floor(numberOfFlows / 500) *
-                                                               one.f.troubleshooting.existingNodes.autoRefreshInterval.refreshRateInterval;
-                                               }
-                                               one.f.troubleshooting.existingNodes.registry.refreshTimer = setTimeout(
-                                                               one.f.troubleshooting.existingNodes.load.flows,
-                                                               refreshRate, nodeId);
-                                       });
-                               } catch(e) {}
-                       },
-                       ports: function(nodeId) {
-                               try {
-                                       clearTimeout(one.f.troubleshooting.existingNodes.registry.refreshTimer);
-                                       $.getJSON(one.main.constants.address.prefix + "/troubleshoot/portStats?nodeId=" + nodeId, function(content) {
-                                               var body = one.f.troubleshooting.existingNodes.data.ports(content);
-                                               var $table = one.f.troubleshooting.createTable(content.columnNames, body);
-                                               $rightBottomDashlet = one.f.troubleshooting.rightBottomDashlet.get();
-                                               one.f.troubleshooting.rightBottomDashlet.setDashletHeader("Ports");
-                                               one.lib.dashlet.empty($rightBottomDashlet);
-                                               $rightBottomDashlet.append(one.lib.dashlet.header("Port Details"));
-                                               $rightBottomDashlet.append($table);
-                                               var numberOfPorts = content.nodeData.length;
-                                               var refreshRate = one.f.troubleshooting.existingNodes.autoRefreshInterval.ports;
-                                               if (numberOfPorts > 0) {
-                                                       refreshRate += Math.floor(numberOfPorts / 500) *
-                                                               one.f.troubleshooting.existingNodes.autoRefreshInterval.refreshRateInterval;
-                                               }
-                                               one.f.troubleshooting.existingNodes.registry.refreshTimer = setTimeout(
-                                                               one.f.troubleshooting.existingNodes.load.ports,
-                                                               refreshRate, nodeId);
-                                       });
-                               } catch(e) {}
-                       } 
-               },
-               ajax : function(url, callback) {
-                       $.getJSON(url, function(data) {
-                               callback(data);
-                       });
-               },
-               registry: {},
-               modal : {
-               },
-               data : {
-                       existingNodes : function(data) {
-                               var result = [];
-                               $.each(data.nodeData, function(key, value) {
-                                       var tr = {};
-                                       var entry = [];
-                                       entry.push(value["nodeName"]);
-                                       entry.push(value["nodeId"]);
-                                       var nodeIdvalue = value["nodeId"];
-                                       entry.push("<a href=\"javascript:one.f.troubleshooting.existingNodes.load.flows('" + value["nodeId"] + "');\">Flows</a>" + 
-                                                       " <a href=\"javascript:one.f.troubleshooting.existingNodes.load.ports('" + value["nodeId"] + "');\">Ports</a>");
-                                       tr.entry = entry;
-                                       result.push(tr);
-                               });
-                               return result;
-                       },
-                       ports: function(data) {
-                               var result = [];
-                               $.each(data.nodeData, function(key, value) {
-                                       var tr = {};
-                                       var entry = [];
-                                       entry.push(value["nodeConnector"]);
-                                       entry.push(value["rxPkts"]);
-                                       entry.push(value["txPkts"]);
-                                       entry.push(value["rxBytes"]);
-                                       entry.push(value["txBytes"]);
-                                       entry.push(value["rxDrops"]);
-                                       entry.push(value["txDrops"]);
-                                       entry.push(value["rxErrors"]);
-                                       entry.push(value["txErrors"]);
-                                       entry.push(value["rxFrameErrors"]);
-                                       entry.push(value["rxOverRunErrors"]);
-                                       entry.push(value["rxCRCErrors"]);
-                                       entry.push(value["collisions"]);
-                                       tr.entry = entry;
-                                       result.push(tr);
-                               });
-                               return result;
-                       },
-                       flows: function(data) {
-                               var result = [];
-                               $.each(data.nodeData, function(key, value) {
-                                       var tr = {};
-                                       var entry = [];
-                                       entry.push(value["nodeName"]);
-                                       entry.push(value["inPort"]);
-                                       entry.push(value["dlSrc"]);
-                                       entry.push(value["dlDst"]);
-                                       entry.push(value["dlType"]);
-                                       entry.push(value["dlVlan"]);
-                                       entry.push(value["nwSrc"]);
-                                       entry.push(value["nwDst"]);
-                                       entry.push(value["nwProto"]);
-                                       entry.push(value["tpSrc"]);
-                                       entry.push(value["tpDst"]);
-                                       entry.push(value["actions"]);
-                                       entry.push(value["byteCount"]);
-                                       entry.push(value["packetCount"]);
-                                       entry.push(value["durationSeconds"]);
-                                       entry.push(value["idleTimeout"]);
-                                       entry.push(value["outPorts"]);
-                                       entry.push(value["outVlanId"]);
-                                       entry.push(value["priority"]);
-                                       tr.entry = entry;
-                                       result.push(tr);
-                               });
-                               return result;
-                       }
-               }
+        id: {
+            popout: "one_f_troubleshooting_existingNodes_id_popout",
+            modal: "one_f_troubleshooting_existingNodes_id_modal",
+            existingNodesDataGrid: "one_f_troubleshooting_existingNodes_id_datagrid",
+            portsDataGrid: "one_f_troubleshooting_existingNodes_id_portsDataGrid",
+            flowsDataGrid: "one_f_troubleshooting_existingNodes_id_flowsDataGrid"
+        },
+        // TODO: Make these values configurable.
+        autoRefreshInterval: {
+            flows: 10000,
+            ports: 10000,
+            refreshRateInterval: 5000
+        },
+        load: {
+            main: function($dashlet) {
+                one.lib.dashlet.empty($dashlet);
+                $dashlet.append(one.lib.dashlet.header(one.f.dashlet.existingNodes.name));
+                // TODO(l): Add a generic auto expand function to one.lib and replace custom height setting.
+                //$('#left-top').height('100%');
+                one.f.troubleshooting.existingNodes.ajax(one.f.troubleshooting.rootUrl + "/existingNodes" , function(content) {
+                    var $gridHTML = one.lib.dashlet.datagrid.init(one.f.troubleshooting.existingNodes.id.existingNodesDataGrid, {
+                        searchable: true,
+                        filterable: false,
+                        pagination: true,
+                        flexibleRowsPerPage: true
+                        }, "table-striped table-condensed");
+                    $dashlet.append($gridHTML);
+                    var dataSource = one.f.troubleshooting.existingNodes.data.existingNodesGrid(content);
+                    $("#" + one.f.troubleshooting.existingNodes.id.existingNodesDataGrid).datagrid({dataSource: dataSource});
+
+                });
+            },
+            flows: function(nodeId) {
+                try {
+                    clearTimeout(one.f.troubleshooting.existingNodes.registry.refreshTimer);
+                    $.getJSON(one.main.constants.address.prefix + "/troubleshoot/flowStats?nodeId=" + nodeId, function(content) {
+                        $rightBottomDashlet = one.f.troubleshooting.rightBottomDashlet.get();
+                        one.f.troubleshooting.rightBottomDashlet.setDashletHeader("Flows");
+                        one.lib.dashlet.empty($rightBottomDashlet);
+                        $rightBottomDashlet.append(one.lib.dashlet.header("Flow Details"));
+
+                        var $gridHTML = one.lib.dashlet.datagrid.init(one.f.troubleshooting.existingNodes.id.flowsDataGrid, {
+                            searchable: true,
+                            filterable: false,
+                            pagination: true,
+                            flexibleRowsPerPage: true
+                            }, "table-striped table-condensed");
+                        $rightBottomDashlet.append($gridHTML);
+                        var dataSource = one.f.troubleshooting.existingNodes.data.flowsGrid(content);
+                        $("#" + one.f.troubleshooting.existingNodes.id.flowsDataGrid).datagrid({dataSource: dataSource});
+
+                        var numberOfFlows = content.nodeData.length;
+                        var refreshRate = one.f.troubleshooting.existingNodes.autoRefreshInterval.flows;
+                        if (numberOfFlows > 0) {
+                            refreshRate += Math.floor(numberOfFlows / 500) *
+                                one.f.troubleshooting.existingNodes.autoRefreshInterval.refreshRateInterval;
+                        }
+                        one.f.troubleshooting.existingNodes.registry.refreshTimer = setTimeout(
+                                one.f.troubleshooting.existingNodes.load.flows,
+                                refreshRate, nodeId);
+                    });
+                } catch(e) {}
+            },
+            ports: function(nodeId) {
+                try {
+                    clearTimeout(one.f.troubleshooting.existingNodes.registry.refreshTimer);
+                    $.getJSON(one.main.constants.address.prefix + "/troubleshoot/portStats?nodeId=" + nodeId, function(content) {
+                        $rightBottomDashlet = one.f.troubleshooting.rightBottomDashlet.get();
+                        one.f.troubleshooting.rightBottomDashlet.setDashletHeader("Ports");
+                        one.lib.dashlet.empty($rightBottomDashlet);
+                        $rightBottomDashlet.append(one.lib.dashlet.header("Port Details"));
+
+                        var $gridHTML = one.lib.dashlet.datagrid.init(one.f.troubleshooting.existingNodes.id.portsDataGrid, {
+                            searchable: true,
+                            filterable: false,
+                            pagination: true,
+                            flexibleRowsPerPage: true
+                            }, "table-striped table-condensed");
+                        $rightBottomDashlet.append($gridHTML);
+                        var dataSource = one.f.troubleshooting.existingNodes.data.portsGrid(content);
+                        $("#" + one.f.troubleshooting.existingNodes.id.portsDataGrid).datagrid({dataSource: dataSource});
+
+                        var numberOfPorts = content.nodeData.length;
+                        var refreshRate = one.f.troubleshooting.existingNodes.autoRefreshInterval.ports;
+                        if (numberOfPorts > 0) {
+                            refreshRate += Math.floor(numberOfPorts / 500) *
+                                one.f.troubleshooting.existingNodes.autoRefreshInterval.refreshRateInterval;
+                        }
+                        one.f.troubleshooting.existingNodes.registry.refreshTimer = setTimeout(
+                                one.f.troubleshooting.existingNodes.load.ports,
+                                refreshRate, nodeId);
+                    });
+                } catch(e) {}
+            } 
+        },
+        ajax : function(url, callback) {
+            $.getJSON(url, function(data) {
+                callback(data);
+            });
+        },
+        registry: {},
+        modal : {
+        },
+        data : {
+            existingNodesGrid: function(data) {
+                var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'nodeName',
+                            label: 'Name',
+                            sortable: true
+                        },
+                        {
+                            property: 'nodeId',
+                            label: 'Static Route',
+                            sortable: true
+                        },
+                        {
+                            property: 'statistics',
+                            label: 'Statistics',
+                            sortable: true
+                        }
+                    ],
+                    data: data.nodeData,
+                    formatter: function(items) {
+                        $.each(items, function(index, item) {
+                            item["statistics"] = "<a href=\"javascript:one.f.troubleshooting.existingNodes.load.flows('" + item["nodeId"] + "');\">Flows</a>" + 
+                            " <a href=\"javascript:one.f.troubleshooting.existingNodes.load.ports('" + item["nodeId"] + "');\">Ports</a>";
+                        });
+
+                    },
+                    delay: 0
+                });
+                return source;
+            },
+            portsGrid: function(data) {
+                var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'nodeConnector',
+                            label: 'Node Connector',
+                            sortable: true
+                        },
+                        {
+                            property: 'rxPkts',
+                            label: 'Rx Pkts',
+                            sortable: true
+                        },
+                        {
+                            property: 'txPkts',
+                            label: 'Tx Pkts',
+                            sortable: true
+                        },
+                        {
+                            property: 'rxBytes',
+                            label: 'Rx Bytes',
+                            sortable: true
+                        },
+                        {
+                            property: 'txBytes',
+                            label: 'Tx Bytes',
+                            sortable: true
+                        },
+                        {
+                            property: 'rxDrops',
+                            label: 'Rx Drops',
+                            sortable: true
+                        },
+                        {
+                            property: 'txDrops',
+                            label: 'Tx Drops',
+                            sortable: true
+                        },
+                        {
+                            property: 'rxErrors',
+                            label: 'Rx Errs',
+                            sortable: true
+                        },
+                        {
+                            property: 'txErrors',
+                            label: 'Tx Errs',
+                            sortable: true
+                        },
+                        {
+                            property: 'rxFrameErrors',
+                            label: 'Rx Frame Errs',
+                            sortable: true
+                        },
+                        {
+                            property: 'rxOverRunErrors',
+                            label: 'Rx OverRun Errs',
+                            sortable: true
+                        },
+                        {
+                            property: 'rxCRCErrors',
+                            label: 'Rx CRC Errs',
+                            sortable: true
+                        },
+                        {
+                            property: 'collisions',
+                            label: 'Collisions',
+                            sortable: true
+                        }
+                    ],
+                    data: data.nodeData,
+                    delay: 200
+                });
+                return source;
+            },
+            ports: function(data) {
+                var result = [];
+                $.each(data.nodeData, function(key, value) {
+                    var tr = {};
+                    var entry = [];
+                    entry.push(value["nodeConnector"]);
+                    entry.push(value["rxPkts"]);
+                    entry.push(value["txPkts"]);
+                    entry.push(value["rxBytes"]);
+                    entry.push(value["txBytes"]);
+                    entry.push(value["rxDrops"]);
+                    entry.push(value["txDrops"]);
+                    entry.push(value["rxErrors"]);
+                    entry.push(value["txErrors"]);
+                    entry.push(value["rxFrameErrors"]);
+                    entry.push(value["rxOverRunErrors"]);
+                    entry.push(value["rxCRCErrors"]);
+                    entry.push(value["collisions"]);
+                    tr.entry = entry;
+                    result.push(tr);
+                });
+                return result;
+            },
+            flowsGrid: function(data) {
+                var source = new StaticDataSource({
+                    columns: [
+                        {
+                            property: 'nodeName',
+                            label: 'Node',
+                            sortable: true
+                        },
+                        {
+                            property: 'inPort',
+                            label: 'In Port',
+                            sortable: true
+                        },
+                        {
+                            property: 'dlSrc',
+                            label: 'DL Src',
+                            sortable: true
+                        },
+                        {
+                            property: 'dlDst',
+                            label: 'DL Dst',
+                            sortable: true
+                        },
+                        {
+                            property: 'dlType',
+                            label: 'DL Type',
+                            sortable: true
+                        },
+                        {
+                            property: 'dlVlan',
+                            label: 'DL Vlan',
+                            sortable: true
+                        },
+                        {
+                            property: 'nwSrc',
+                            label: 'NW Src',
+                            sortable: true
+                        },
+                        {
+                            property: 'nwDst',
+                            label: 'NW Dst',
+                            sortable: true
+                        },
+                        {
+                            property: 'nwProto',
+                            label: 'NW Proto',
+                            sortable: true
+                        },
+                        {
+                            property: 'tpSrc',
+                            label: 'TP Src',
+                            sortable: true
+                        },
+                        {
+                            property: 'tpDst',
+                            label: 'TP Dst',
+                            sortable: true
+                        },
+                        {
+                            property: 'actions',
+                            label: 'Actions',
+                            sortable: true
+                        },
+                        {
+                            property: 'byteCount',
+                            label: 'Byte Count',
+                            sortable: true
+                        },
+                        {
+                            property: 'packetCount',
+                            label: 'Packet Count',
+                            sortable: true
+                        },
+                        {
+                            property: 'durationSeconds',
+                            label: 'Duration Seconds',
+                            sortable: true
+                        },
+                        {
+                            property: 'idleTimeout',
+                            label: 'Idle Timeout',
+                            sortable: true
+                        },
+                        {
+                            property: 'outPorts',
+                            label: 'Out Ports',
+                            sortable: true
+                        },
+                        {
+                            property: 'outVlanId',
+                            label: 'Out VlanId',
+                            sortable: true
+                        },
+                        {
+                            property: 'priority',
+                            label: 'Priority',
+                            sortable: true
+                        }
+                    ],
+                    data: data.nodeData,
+                    delay: 0
+                });
+                return source;
+            },
+            flows: function(data) {
+                var result = [];
+                $.each(data.nodeData, function(key, value) {
+                    var tr = {};
+                    var entry = [];
+                    entry.push(value["nodeName"]);
+                    entry.push(value["inPort"]);
+                    entry.push(value["dlSrc"]);
+                    entry.push(value["dlDst"]);
+                    entry.push(value["dlType"]);
+                    entry.push(value["dlVlan"]);
+                    entry.push(value["nwSrc"]);
+                    entry.push(value["nwDst"]);
+                    entry.push(value["nwProto"]);
+                    entry.push(value["tpSrc"]);
+                    entry.push(value["tpDst"]);
+                    entry.push(value["actions"]);
+                    entry.push(value["byteCount"]);
+                    entry.push(value["packetCount"]);
+                    entry.push(value["durationSeconds"]);
+                    entry.push(value["idleTimeout"]);
+                    entry.push(value["outPorts"]);
+                    entry.push(value["outVlanId"]);
+                    entry.push(value["priority"]);
+                    tr.entry = entry;
+                    result.push(tr);
+                });
+                return result;
+            }
+        }
 };
 
 one.f.troubleshooting.uptime = {
-       id: {
-               popout: "one_f_troubleshooting_existingNodes_id_popout",
-               modal: "one_f_troubleshooting_existingNodes_id_modal"
-       },
+    id: {
+        popout: "one_f_troubleshooting_uptime_id_popout",
+        modal: "one_f_troubleshooting_uptime_id_modal",
+        datagrid: "one_f_troubleshooting_uptime_id_datagrid"
+    },
 
-       dashlet: function($dashlet) {
-                       one.lib.dashlet.empty($dashlet);
-                       $dashlet.append(one.lib.dashlet.header(one.f.dashlet.uptime.name));
-                       var url = one.f.troubleshooting.rootUrl + "/uptime";
-                       one.f.troubleshooting.uptime.ajax.main(url , {} ,function(content) {
-                               var body = one.f.troubleshooting.uptime.data.uptime(content);
-                               var $table = one.f.troubleshooting.createTable(content.columnNames, body);
-                               $dashlet.append($table);
-                       });
-       },
-       
-       ajax : {
-               main : function(url, requestData, callback) {
-                       $.getJSON(url, requestData, function(data) {
-                               callback(data);
-                       });
-               }
-       },
-       
-       data: {
-               uptime: function(data) {
-                       var result = [];
-                       $.each(data.nodeData, function(key, value) {
-                               var tr = {};
-                               var entry = [];
-                               entry.push(value["nodeName"]);
-                               entry.push(value["nodeId"]);
-                               entry.push(value["connectedSince"]);
-                               tr.entry = entry;
-                               result.push(tr);
-                       });
-                       return result;
-               }
-       },
+    dashlet: function($dashlet) {
+            one.lib.dashlet.empty($dashlet);
+            $dashlet.append(one.lib.dashlet.header(one.f.dashlet.uptime.name));
+            var url = one.f.troubleshooting.rootUrl + "/uptime";
+            one.f.troubleshooting.uptime.ajax.main(url , {} ,function(content) {
+                var $gridHTML = one.lib.dashlet.datagrid.init(one.f.troubleshooting.uptime.id.datagrid, {
+                    searchable: true,
+                    filterable: false,
+                    pagination: true,
+                    flexibleRowsPerPage: true
+                    }, "table-striped table-condensed");
+                $dashlet.append($gridHTML);
+                var dataSource = one.f.troubleshooting.uptime.data.uptimeDataGrid(content);
+                $("#" + one.f.troubleshooting.uptime.id.datagrid).datagrid({dataSource: dataSource});
+            });
+    },
+    
+    ajax : {
+        main : function(url, requestData, callback) {
+            $.getJSON(url, requestData, function(data) {
+                callback(data);
+            });
+        }
+    },
+    
+    data: {
+        uptimeDataGrid: function(data) {
+            var source = new StaticDataSource({
+                columns: [
+                    {
+                        property: 'nodeName',
+                        label: 'Node',
+                        sortable: true
+                    },
+                    {
+                        property: 'nodeId',
+                        label: 'Node ID',
+                        sortable: true
+                    },
+                    {
+                        property: 'connectedSince',
+                        label: 'Statistics',
+                        sortable: true
+                    }
+                ],
+                data: data.nodeData,
+                delay: 0
+            });
+            return source;
+        },
+        uptime: function(data) {
+            var result = [];
+            $.each(data.nodeData, function(key, value) {
+                var tr = {};
+                var entry = [];
+                entry.push(value["nodeName"]);
+                entry.push(value["nodeId"]);
+                entry.push(value["connectedSince"]);
+                tr.entry = entry;
+                result.push(tr);
+            });
+            return result;
+        }
+    },
 };
 
 one.f.troubleshooting.statistics = {
-       dashlet : function($dashlet) {
+    dashlet : function($dashlet) {
         var $h4 = one.lib.dashlet.header("Statistics");
         $dashlet.append($h4);
-               // empty
-               var $none = $(document.createElement('div'));
-               $none.addClass('none');
-               var $p = $(document.createElement('p'));
-               $p.text('Please select a Flow or Ports statistics');
-               $p.addClass('text-center').addClass('text-info');
-               
-               $dashlet.append($none)
-                       .append($p);
-       }
+        // empty
+        var $none = $(document.createElement('div'));
+        $none.addClass('none');
+        var $p = $(document.createElement('p'));
+        $p.text('Please select a Flow or Ports statistics');
+        $p.addClass('text-center').addClass('text-info');
+        
+        $dashlet.append($none)
+            .append($p);
+    }
 };
 
 // bind dashlet nav
@@ -308,14 +557,14 @@ $('.dash .nav a', '#main').click(function() {
     var menu = one.f.dashlet;
     switch (id) {
         case menu.existingNodes.id:
-               one.f.troubleshooting.existingNodes.load.main($dashlet);
+            one.f.troubleshooting.existingNodes.load.main($dashlet);
             break;
         case menu.uptime.id:
-               one.f.troubleshooting.uptime.dashlet($dashlet);
-                       break;
-               case menu.flowsOrPorts.id:
-                       one.f.troubleshooting.statistics.dashlet($dashlet);
-                       break;
+            one.f.troubleshooting.uptime.dashlet($dashlet);
+            break;
+        case menu.flowsOrPorts.id:
+            one.f.troubleshooting.statistics.dashlet($dashlet);
+            break;
     };
 });