cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jessicaw...@apache.org
Subject [05/39] Format JS
Date Fri, 19 Jul 2013 17:01:18 GMT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f766a9e5/ui/scripts/ui/widgets/listView.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js
index bc68a72..4fd0b7f 100644
--- a/ui/scripts/ui/widgets/listView.js
+++ b/ui/scripts/ui/widgets/listView.js
@@ -18,2033 +18,2033 @@
  * Create dynamic list view based on data callbacks
  */
 (function($, cloudStack, _l, _s) {
-  var uiActions = {
-    standard: function($instanceRow, args, additional) {
-      var listViewArgs = $instanceRow.closest('div.list-view').data('view-args');
-      var notification = args.action.notification ? args.action.notification : {};
-      var messages = args.action ? args.action.messages : {};
-      var preAction = args.action ? args.action.preAction : {};
-      var action = args.action ? args.action.action : {};
-      var needsRefresh = args.action.needsRefresh;
-      var section;
-      var data = {
-        id: $instanceRow.data('list-view-item-id'),
-        jsonObj: $instanceRow.data('jsonObj')
-      };
-      var $listView = $instanceRow.closest('.list-view');
-      var messageArgs = {
-        name: $instanceRow.find('td.name span').html()
-      };
-
-      if (args.data) $.extend(true, data, args.data);
-      if (listViewArgs) section = listViewArgs.section;
-
-      notification.desc = messages ?
-        messages.notification(messageArgs) : null;
-
-      if (listViewArgs)
-        notification.section = listViewArgs.id;
-
-      // Handle pre-action (occurs before any other behavior happens)
-      if (preAction) {
-        var preActionContext = $.extend(true, {}, listViewArgs.context);
-
-        preActionContext[
-          listViewArgs.activeSection
-        ] = [$instanceRow.data('jsonObj')];
-
-        if (!preAction({ context: preActionContext })) return false;
-      }
-
-      var performAction = function(data, options) {
-        if (!options) options = {};
+    var uiActions = {
+        standard: function($instanceRow, args, additional) {
+            var listViewArgs = $instanceRow.closest('div.list-view').data('view-args');
+            var notification = args.action.notification ? args.action.notification : {};
+            var messages = args.action ? args.action.messages : {};
+            var preAction = args.action ? args.action.preAction : {};
+            var action = args.action ? args.action.action : {};
+            var needsRefresh = args.action.needsRefresh;
+            var section;
+            var data = {
+                id: $instanceRow.data('list-view-item-id'),
+                jsonObj: $instanceRow.data('jsonObj')
+            };
+            var $listView = $instanceRow.closest('.list-view');
+            var messageArgs = {
+                name: $instanceRow.find('td.name span').html()
+            };
 
-        var $form = options.$form;
-        var isHeader = options.isHeader;
-
-        $instanceRow = options.$item ? options.$item : $instanceRow;
-        var $item = options.$item;
-        var context = $.extend(true, {}, listViewArgs.context);
-        context[
-          listViewArgs.activeSection
-        ] = [$instanceRow.data('jsonObj')];
-
-        var externalLinkAction = action.externalLink;
-        if (externalLinkAction) {
-          // Show popup immediately, do not proceed through normal action process
-          window.open(
-            // URL
-            externalLinkAction.url({
-              context: context
-            }),
+            if (args.data) $.extend(true, data, args.data);
+            if (listViewArgs) section = listViewArgs.section;
 
-            // Title
-            externalLinkAction.title({
-              context: context
-            }),
+            notification.desc = messages ?
+                messages.notification(messageArgs) : null;
 
-            // Window options
-            'menubar=0,resizable=0,'
-              + 'width=' + externalLinkAction.width + ','
-              + 'height=' + externalLinkAction.height
-          );
-        } else if (action.custom && !action.noAdd) {
-          action.custom({
-            data: data,
-            ref: options.ref,
-            context: context,
-            $instanceRow: $instanceRow,
-            complete: function(args) {
-              args = args ? args : {};
-
-              var $item = args.$item;
-
-              notification.desc = messages.notification(args.messageArgs);
-              notification._custom = args._custom;
-
-              cloudStack.ui.notifications.add(
-                notification,
-                function(args) {
-                  if (listViewArgs.onActionComplete) {
-                    listViewArgs.onActionComplete();
-                  }
-                  
-                  if ($item.is(':visible') && !isHeader) {
-                    replaceItem(
-                      $item,
-                      args.data,
-                      args.actionFilter ?
-                        args.actionFilter : $instanceRow.next().data('list-view-action-filter')
-                    );
-                  }
-                },
+            if (listViewArgs)
+                notification.section = listViewArgs.id;
 
-                {},
-
-                // Error
-                function(args) {
-									if (args && args.updatedData) {
-										if ($item.is(':visible') && !isHeader) {
-											replaceItem(
-												$item,
-												args.updatedData,
-												args.actionFilter
-											);
-										}
-									} else {
-										$item.remove();
-									}
-                }
-              );
+            // Handle pre-action (occurs before any other behavior happens)
+            if (preAction) {
+                var preActionContext = $.extend(true, {}, listViewArgs.context);
+
+                preActionContext[
+                    listViewArgs.activeSection
+                ] = [$instanceRow.data('jsonObj')];
+
+                if (!preAction({
+                    context: preActionContext
+                })) return false;
             }
-          });
-        } else if (action.uiCustom) {
-          action.uiCustom({
-            $item: $instanceRow
-          });
-        } else {
-          if (needsRefresh) {
-            var $loading = $('<div>').addClass('loading-overlay');
-            
-            $listView.prepend($loading);
-          }
-          
-          var actionArgs = {
-            data: data,
-            ref: options.ref,
-            context: options.context,
-            $form: $form,
-            response: {
-              success: function(args) {
-                args = args ? args : {};
-
-                var $prevRow, $newRow;
-
-                // Make copy of previous row, in case data is needed
-                $prevRow = $instanceRow.clone();
-                $prevRow.data($instanceRow.data());
-
-                // Set loading appearance
-                if (args.data && !isHeader) {
-                  $instanceRow = replaceItem(
-                    $instanceRow,
-                    $.extend($instanceRow.data('json-obj'), args.data),
-                    $instanceRow.data('list-view-action-filter')
-                  );
-                }
 
-                $instanceRow.find('td:last').children().remove();
-                $instanceRow.find('td:last').append($('<div>').addClass('loading'));
-                $instanceRow.addClass('loading');
+            var performAction = function(data, options) {
+                if (!options) options = {};
+
+                var $form = options.$form;
+                var isHeader = options.isHeader;
+
+                $instanceRow = options.$item ? options.$item : $instanceRow;
+                var $item = options.$item;
+                var context = $.extend(true, {}, listViewArgs.context);
+                context[
+                    listViewArgs.activeSection
+                ] = [$instanceRow.data('jsonObj')];
+
+                var externalLinkAction = action.externalLink;
+                if (externalLinkAction) {
+                    // Show popup immediately, do not proceed through normal action process
+                    window.open(
+                        // URL
+                        externalLinkAction.url({
+                            context: context
+                        }),
+
+                        // Title
+                        externalLinkAction.title({
+                            context: context
+                        }),
+
+                        // Window options
+                        'menubar=0,resizable=0,' + 'width=' + externalLinkAction.width + ',' + 'height=' + externalLinkAction.height
+                    );
+                } else if (action.custom && !action.noAdd) {
+                    action.custom({
+                        data: data,
+                        ref: options.ref,
+                        context: context,
+                        $instanceRow: $instanceRow,
+                        complete: function(args) {
+                            args = args ? args : {};
+
+                            var $item = args.$item;
+
+                            notification.desc = messages.notification(args.messageArgs);
+                            notification._custom = args._custom;
+
+                            cloudStack.ui.notifications.add(
+                                notification,
+                                function(args) {
+                                    if (listViewArgs.onActionComplete) {
+                                        listViewArgs.onActionComplete();
+                                    }
+
+                                    if ($item.is(':visible') && !isHeader) {
+                                        replaceItem(
+                                            $item,
+                                            args.data,
+                                            args.actionFilter ?
+                                            args.actionFilter : $instanceRow.next().data('list-view-action-filter')
+                                        );
+                                    }
+                                },
+
+                                {},
+
+                                // Error
+
+                                function(args) {
+                                    if (args && args.updatedData) {
+                                        if ($item.is(':visible') && !isHeader) {
+                                            replaceItem(
+                                                $item,
+                                                args.updatedData,
+                                                args.actionFilter
+                                            );
+                                        }
+                                    } else {
+                                        $item.remove();
+                                    }
+                                }
+                            );
+                        }
+                    });
+                } else if (action.uiCustom) {
+                    action.uiCustom({
+                        $item: $instanceRow
+                    });
+                } else {
+                    if (needsRefresh) {
+                        var $loading = $('<div>').addClass('loading-overlay');
 
-                if (options.$item) $instanceRow.data('list-view-new-item', true);
+                        $listView.prepend($loading);
+                    }
 
-                // Disable any clicking/actions for row
-                $instanceRow.bind('click', function() { return false; });
+                    var actionArgs = {
+                        data: data,
+                        ref: options.ref,
+                        context: options.context,
+                        $form: $form,
+                        response: {
+                            success: function(args) {
+                                args = args ? args : {};
+
+                                var $prevRow, $newRow;
+
+                                // Make copy of previous row, in case data is needed
+                                $prevRow = $instanceRow.clone();
+                                $prevRow.data($instanceRow.data());
+
+                                // Set loading appearance
+                                if (args.data && !isHeader) {
+                                    $instanceRow = replaceItem(
+                                        $instanceRow,
+                                        $.extend($instanceRow.data('json-obj'), args.data),
+                                        $instanceRow.data('list-view-action-filter')
+                                    );
+                                }
+
+                                $instanceRow.find('td:last').children().remove();
+                                $instanceRow.find('td:last').append($('<div>').addClass('loading'));
+                                $instanceRow.addClass('loading');
+
+                                if (options.$item) $instanceRow.data('list-view-new-item', true);
+
+                                // Disable any clicking/actions for row
+                                $instanceRow.bind('click', function() {
+                                    return false;
+                                });
+
+                                notification._custom = args._custom;
+
+                                if (additional && additional.success) additional.success(args);
+
+                                if (listViewArgs.onActionComplete == true) {
+                                    listViewArgs.onActionComplete();
+                                }
+
+                                cloudStack.ui.notifications.add(
+                                    notification,
+
+                                    // Success
+
+                                    function(args) {
+                                        if (!args) args = {};
+
+                                        var actionFilter = args.actionFilter ?
+                                            args.actionFilter : $instanceRow.data('list-view-action-filter');
+
+                                        if (!isHeader) {
+                                            if ($instanceRow.is(':visible')) {
+                                                if (args.data) {
+                                                    $newRow = replaceItem($instanceRow,
+                                                        $.extend($instanceRow.data('json-obj'), args.data),
+                                                        actionFilter);
+                                                } else {
+                                                    // Nothing new, so just put in existing data
+                                                    $newRow = replaceItem($instanceRow,
+                                                        $instanceRow.data('json-obj'),
+                                                        actionFilter);
+                                                }
+
+                                                if (needsRefresh) {
+                                                    if ($listView.closest('.detail-view').size()) {
+                                                        $('.detail-view:last .button.refresh').click();
+                                                    } else {
+                                                        $loading.remove();
+                                                        $listView.listView('refresh');
+                                                    }
+                                                }
+                                            }
+
+                                            if (additional && additional.complete)
+                                                additional.complete(args, $newRow);
+                                        }
+
+                                        if (messages.complete) {
+                                            cloudStack.dialog.notice({
+                                                message: messages.complete(args.data)
+                                            });
+                                        }
+
+                                        if (options.complete) {
+                                            options.complete(args);
+                                        }
+
+                                        if (listViewArgs.onActionComplete) {
+                                            listViewArgs.onActionComplete();
+                                        }
+                                    },
+
+                                    {},
+
+                                    // Error
+
+                                    function(args) {
+                                        if (!isHeader) {
+                                            if ($instanceRow.data('list-view-new-item')) {
+                                                // For create forms
+                                                $instanceRow.remove();
+                                            } else {
+                                                // For standard actions
+                                                replaceItem(
+                                                    $instanceRow,
+                                                    $.extend($instanceRow.data('json-obj'), args.data),
+                                                    args.actionFilter ?
+                                                    args.actionFilter :
+                                                    $instanceRow.data('list-view-action-filter')
+                                                );
+                                            }
+                                        }
+
+                                        if (options.error) {
+                                            options.error(args);
+                                        }
+                                    }
+                                );
+                            },
+                            error: function(message) {
+                                if (!isHeader) {
+                                    if (($.isPlainObject(args.action.createForm) && args.action.addRow != 'false') ||
+                                        (!args.action.createForm && args.action.addRow == 'true')) {
+                                        $instanceRow.remove();
+                                    }
+                                }
+
+                                if (options.error) options.error(message);
+
+                                if (message) cloudStack.dialog.notice({
+                                    message: message
+                                });
+                            }
+                        }
+                    };
+
+                    if (action.custom && action.noAdd) {
+                        action.custom({
+                            data: data,
+                            ref: options.ref,
+                            context: context,
+                            $instanceRow: $instanceRow,
+                            complete: actionArgs.response.success
+                        });
+                    } else {
+                        action(actionArgs);
+                    }
+                }
+            };
 
-                notification._custom = args._custom;
+            var context = $.extend({}, listViewArgs.context);
 
-                if (additional && additional.success) additional.success(args);
+            context[
+                listViewArgs.activeSection
+            ] = [$instanceRow.data('jsonObj')];
 
-                if (listViewArgs.onActionComplete == true) {
-                  listViewArgs.onActionComplete();
-                }
-                
-                cloudStack.ui.notifications.add(
-                  notification,
-
-                  // Success
-                  function(args) {
-                    if (!args) args = {};
-
-                    var actionFilter = args.actionFilter ?
-                          args.actionFilter : $instanceRow.data('list-view-action-filter');
-
-                    if (!isHeader) {
-                      if ($instanceRow.is(':visible')) {
-                        if (args.data) {
-                          $newRow = replaceItem($instanceRow,
-                                                $.extend($instanceRow.data('json-obj'), args.data),
-                                                actionFilter);
-                        }
-                        else {
-                          // Nothing new, so just put in existing data
-                          $newRow = replaceItem($instanceRow,
-                                                $instanceRow.data('json-obj'),
-                                                actionFilter);
-                        }
+            messageArgs.context = context;
 
-                        if (needsRefresh) {
-                          if ($listView.closest('.detail-view').size()) {
-                            $('.detail-view:last .button.refresh').click();
-                          } else {                            
-                            $loading.remove();
-                            $listView.listView('refresh');
-                          }
+            if (!args.action.action.externalLink && !args.action.createForm &&
+                args.action.addRow != 'true' && !action.custom && !action.uiCustom && !args.action.listView) {
+                cloudStack.dialog.confirm({
+                    message: messages.confirm(messageArgs),
+                    action: function() {
+                        performAction({
+                            id: $instanceRow.data('list-view-item-id')
+                        }, {
+                            context: context
+                        });
+                    }
+                });
+            } else if (action.custom || action.uiCustom) {
+                performAction();
+            } else if (args.action.listView) {
+                cloudStack.dialog.listView({
+                    context: context,
+                    listView: args.action.listView,
+                    after: function(args) {
+                        performAction(null, {
+                            context: args.context
+                        });
+                    }
+                });
+            } else {
+                var addRow = args.action.addRow == "false" ? false : true;
+                var isHeader = args.action.isHeader;
+                var createFormContext = $.extend({}, context);
+
+                var externalLinkAction = action.externalLink;
+                if (externalLinkAction) {
+                    // Show popup immediately, do not proceed through normal action process
+                    window.open(
+                        // URL
+                        externalLinkAction.url({
+                            context: context
+                        }),
+
+                        // Title
+                        externalLinkAction.title({
+                            context: context
+                        }),
+
+                        // Window options
+                        'menubar=0,resizable=0,' + 'width=' + externalLinkAction.width + ',' + 'height=' + externalLinkAction.height
+                    );
+                } else if (args.action.createForm) {
+                    cloudStack.dialog.createForm({
+                        form: args.action.createForm,
+                        after: function(args) {
+                            var $newItem;
+
+                            if (!isHeader) {
+                                if (addRow != false) {
+                                    $newItem = $listView.listView('prependItem', {
+                                        data: [
+                                            $.extend(args.data, {
+                                                state: 'Creating',
+                                                status: 'Creating',
+                                                allocationstate: 'Creating'
+                                            })
+                                        ]
+                                    });
+                                } else {
+                                    $newItem = $instanceRow;
+                                }
+
+                                performAction(args.data, {
+                                    ref: args.ref,
+                                    context: createFormContext,
+                                    $item: $newItem,
+                                    $form: args.$form
+                                });
+                            } else {
+                                var $loading = $('<div>').addClass('loading-overlay');
+
+                                $loading.appendTo($listView);
+                                performAction(args.data, {
+                                    ref: args.ref,
+                                    context: createFormContext,
+                                    $form: args.$form,
+                                    isHeader: isHeader,
+                                    complete: function(args) {
+                                        $loading.remove();
+                                        $listView.listView('refresh');
+                                    },
+                                    error: function(args) {
+                                        $loading.remove();
+                                    }
+                                });
+                            }
+                        },
+                        ref: listViewArgs.ref,
+                        context: createFormContext
+                    });
+                } else {
+                    cloudStack.dialog.confirm({
+                        message: messages.confirm(messageArgs),
+                        action: function() {
+                            var $newItem;
+                            if (addRow && !action.isHeader) {
+                                $newItem = $listView.listView('prependItem', {
+                                    data: [
+                                        $.extend(args.data, {
+                                            state: 'Creating',
+                                            status: 'Creating',
+                                            allocationstate: 'Creating'
+                                        })
+                                    ]
+                                });
+                            } else if (action.isHeader) {
+                                $newItem = $('<div>');
+                            } else {
+                                $newItem = $instanceRow;
+                            }
+
+                            performAction(args.data, {
+                                ref: args.ref,
+                                context: createFormContext,
+                                $item: $newItem,
+                                $form: args.$form
+                            });
                         }
-                      }
+                    });
+                }
+            }
+        },
 
-                      if (additional && additional.complete)
-                        additional.complete(args, $newRow);
-                    }
+        remove: function($instanceRow, args) {
+            uiActions.standard($instanceRow, args, {
+                complete: function(args, $newRow) {
+                    $newRow.remove();
+                }
+            });
+        },
 
-                    if (messages.complete) {
-                      cloudStack.dialog.notice({
-                        message: messages.complete(args.data)
-                      });
-                    }
+        edit: function($instanceRow, args) {
+            var $td = $instanceRow.find('td.editable');
+            var $edit = $td.find('div.edit');
+            var $editInput = $edit.find('input');
+            var $label = $td.find('span');
+            var $listView = $instanceRow.closest('.list-view');
+            var listViewArgs = $listView.data('view-args');
+
+            // Hide label, show edit field
+            var showEditField = function() {
+                $edit.css({
+                    opacity: 1
+                });
+                $label.fadeOut('fast', function() {
+                    $edit.fadeIn();
+                    $editInput.focus();
+                    $instanceRow.closest('div.data-table').dataTable('refresh');
+                });
+            };
 
-                    if (options.complete) {
-                      options.complete(args);
+            // Hide edit field, validate and save changes
+            var showLabel = function(val, options) {
+                if (!options) options = {};
+
+                var oldVal = $label.html();
+
+                if (val != null)
+                    $label.html(_s(val));
+
+                var data = {
+                    id: $instanceRow.data('list-view-item-id'),
+                    jsonObj: $instanceRow.data('jsonObj')
+                };
+
+                data[$td.data('list-view-item-field')] = $editInput.val();
+
+                var context = $.extend({}, listViewArgs.context);
+                context[
+                    listViewArgs.activeSection
+                ] = $instanceRow.data('jsonObj');
+
+                args.callback({
+                    data: data,
+                    context: context,
+                    response: {
+                        success: function(args) {
+                            $edit.hide();
+                            $label.fadeIn();
+                            $instanceRow.closest('div.data-table').dataTable('refresh');
+
+                            if (options.success) options.success(args);
+                        },
+                        error: function(message) {
+                            if (message) {
+                                cloudStack.dialog.notice({
+                                    message: message
+                                });
+                                $edit.hide(),
+                                $label.html(_s(oldVal)).fadeIn();
+                                $instanceRow.closest('div.data-table').dataTable('refresh');
+
+                                if (options.error) options.error(args);
+                            }
+                        }
                     }
+                });
+            };
 
-                    if (listViewArgs.onActionComplete) {
-                      listViewArgs.onActionComplete();
-                    }
-                  },
-
-                  {},
-
-                  // Error
-                  function(args) {
-                    if (!isHeader) {
-                      if ($instanceRow.data('list-view-new-item')) {
-                        // For create forms
-                        $instanceRow.remove();
-                      } else {
-                        // For standard actions
-                        replaceItem(
-                          $instanceRow,
-                          $.extend($instanceRow.data('json-obj'), args.data),
-                          args.actionFilter ?
-                            args.actionFilter :
-                            $instanceRow.data('list-view-action-filter')
+            if (args.cancel) { //click Cancel button
+                // showLabel();
+                var oldVal = $label.html();
+                $edit.hide();
+                $label.fadeIn();
+                $instanceRow.closest('div.data-table').dataTable('refresh');
+                $editInput.val(_s(oldVal));
+                return false;
+            }
+
+            if (!$editInput.is(':visible') || !(typeof(args.action) == 'undefined')) { //click Edit button
+                showEditField();
+            } else if ($editInput.val() != $label.html()) { //click Save button with changed value
+                $edit.animate({
+                    opacity: 0.5
+                });
+
+                var originalName = $label.html();
+                var newName = $editInput.val();
+                showLabel(newName, {
+                    success: function() {
+                        cloudStack.ui.notifications.add({
+                                section: $instanceRow.closest('div.view').data('view-args').id,
+                                desc: newName ? _l('Set value of') + ' ' + $instanceRow.find('td.name span').html() + ' ' + _l('to') + ' ' + _s(newName) : _l('Unset value for') + ' ' + $instanceRow.find('td.name span').html()
+                            },
+                            function(args) {}, [{
+                                name: newName
+                            }]
                         );
-                      }
                     }
+                });
+            } else { //click Save button with unchanged value
+                showLabel();
+            }
 
-                    if (options.error) {
-                      options.error(args);
-                    }
-                  }
-                );
-              },
-              error: function(message) {
-                if (!isHeader) {
-                  if (($.isPlainObject(args.action.createForm) && args.action.addRow != 'false') ||
-                      (!args.action.createForm && args.action.addRow == 'true')) {
-                    $instanceRow.remove();
-                  }
-                }
+            return $instanceRow;
+        }
+    };
 
-                if (options.error) options.error(message);
+    var rowActions = {
+        _std: function($tr, action) {
+            action();
 
-                if (message) cloudStack.dialog.notice({ message: message });
-              }
-            }
-          };
-
-          if (action.custom && action.noAdd) {
-            action.custom({
-              data: data,
-              ref: options.ref,
-              context: context,
-              $instanceRow: $instanceRow,
-              complete: actionArgs.response.success
+            $tr.closest('.data-table').dataTable('refresh');
+
+            setTimeout(function() {
+                $tr.closest('.data-table').dataTable('selectRow', $tr.index());
+            }, 0);
+        },
+
+        moveTop: function($tr) {
+            rowActions._std($tr, function() {
+                $tr.closest('tbody').prepend($tr);
+                $tr.closest('.list-view').animate({
+                    scrollTop: 0
+                });
             });
-          } else {
-            action(actionArgs);
-          }
-        }
-      };
-
-      var context = $.extend({}, listViewArgs.context);
-      
-      context[
-        listViewArgs.activeSection
-      ] = [$instanceRow.data('jsonObj')];
-
-      messageArgs.context = context;     
-
-      if (!args.action.action.externalLink &&
-          !args.action.createForm &&
-          args.action.addRow != 'true' &&
-          !action.custom && !action.uiCustom &&
-          !args.action.listView) {
-        cloudStack.dialog.confirm({
-          message: messages.confirm(messageArgs),
-          action: function() {
-            performAction({
-              id: $instanceRow.data('list-view-item-id')
-            }, {
-              context: context
+        },
+
+        moveBottom: function($tr) {
+            rowActions._std($tr, function() {
+                $tr.closest('tbody').append($tr);
+                $tr.closest('.list-view').animate({
+                    scrollTop: 0
+                });
+            });
+        },
+
+        moveUp: function($tr) {
+            rowActions._std($tr, function() {
+                $tr.prev().before($tr);
             });
-          }
+        },
+
+        moveDown: function($tr) {
+            rowActions._std($tr, function() {
+                $tr.next().after($tr);
+            });
+        },
+
+        moveTo: function($tr, index, after) {
+            rowActions._std($tr, function() {
+                var $target = $tr.closest('tbody').find('tr').filter(function() {
+                    return $(this).index() == index;
+                });
+
+                //    if ($target.index() > $tr.index()) $target.after($tr);
+                //  else $target.before($tr);
+
+                $tr.closest('.list-view').scrollTop($tr.position().top - $tr.height() * 2);
+
+                if (after)
+                    setTimeout(function() {
+                        after();
+                    });
+            });
+        }
+    };
+
+    /**
+     * Edit field text
+     *
+     * @param $td {jQuery} <td> to put input field into
+     */
+    var createEditField = function($td) {
+        $td.addClass('editable');
+
+        // Put <td> label into a span
+        var sanitizedValue = $td.html();
+        $('<span></span>').html(sanitizedValue).appendTo($td.html(''));
+
+        var $editArea = $('<div></div>').addClass('edit');
+        var $editField = $('<input />').addClass('edit').attr({
+            type: 'text',
+            value: cloudStack.sanitizeReverse(sanitizedValue)
         });
-      } else if (action.custom || action.uiCustom) {
-        performAction();
-      } else if (args.action.listView) {
-        cloudStack.dialog.listView({
-          context: context,
-          listView: args.action.listView,
-          after: function(args) {
-            performAction(null, { context: args.context });
-          }
+        var $actionButton = $('<div></div>').addClass('action');
+        var $saveButton = $actionButton.clone().addClass('save').attr({
+            'title': _l('Save')
         });
-      } else {
-        var addRow = args.action.addRow == "false" ? false : true;
-        var isHeader = args.action.isHeader;
-        var createFormContext = $.extend({}, context);
-
-        var externalLinkAction = action.externalLink;
-        if (externalLinkAction) {
-          // Show popup immediately, do not proceed through normal action process
-          window.open(
-            // URL
-            externalLinkAction.url({
-              context: context
-            }),
+        var $cancelButton = $actionButton.clone().addClass('cancel').attr({
+            'title': _l('Cancel edit')
+        });
+
+        $([$editField, $saveButton, $cancelButton]).each(function() {
+            this.appendTo($editArea);
+        });
+
+        return $editArea.hide();
+    };
 
-            // Title
-            externalLinkAction.title({
-              context: context
+    var renderActionCol = function(actions) {
+        return $.grep(
+            $.map(actions, function(value, key) {
+                return key;
             }),
+            function(elem) {
+                return elem != 'add';
+            }
+        ).length;
+    };
 
-            // Window options
-            'menubar=0,resizable=0,'
-              + 'width=' + externalLinkAction.width + ','
-              + 'height=' + externalLinkAction.height
-          );
-        } else if (args.action.createForm) {
-          cloudStack.dialog.createForm({
-            form: args.action.createForm,
-            after: function(args) {
-              var $newItem;
-
-              if (!isHeader) {
-                if (addRow != false) {
-                  $newItem = $listView.listView('prependItem', {
-                    data: [
-                      $.extend(args.data, {
-                        state: 'Creating',
-                        status: 'Creating',
-                        allocationstate: 'Creating'
-                      })
-                    ]
-                  });
-                } else {
-                  $newItem = $instanceRow;
-                }
+    var createHeader = function(preFilter, fields, $table, actions, options) {
+        if (!options) options = {};
 
-                performAction(args.data, {
-                  ref: args.ref,
-                  context: createFormContext,
-                  $item: $newItem,
-                  $form: args.$form
-                });
-              } else {
-                var $loading = $('<div>').addClass('loading-overlay');
+        var $thead = $('<thead>').prependTo($table).append($('<tr>'));
+        var reorder = options.reorder;
+        var detailView = options.detailView;
+        var viewArgs = $table.closest('.list-view').data('view-args');
+        var uiCustom = viewArgs.uiCustom;
+        var hiddenFields = [];
 
-                $loading.appendTo($listView);
-                performAction(args.data, {
-                  ref: args.ref,
-                  context: createFormContext,
-                  $form: args.$form,
-                  isHeader: isHeader,
-                  complete: function(args) {
-                    $loading.remove();
-                    $listView.listView('refresh');
-                  },
-                  error: function(args) {
-                    $loading.remove();
-                  }
-                });
-              }
-            },
-            ref: listViewArgs.ref,
-            context: createFormContext
-          });
-        } else {
-          cloudStack.dialog.confirm({
-            message: messages.confirm(messageArgs),
-            action: function() {
-              var $newItem;
-              if (addRow && !action.isHeader) {
-                $newItem = $listView.listView('prependItem', {
-                  data: [
-                    $.extend(args.data, {
-                      state: 'Creating',
-                      status: 'Creating',
-                      allocationstate: 'Creating'
-                    })
-                  ]
-                });
-              } else if (action.isHeader) {
-                $newItem = $('<div>');
-              } else {
-                $newItem = $instanceRow;
-              }
-
-              performAction(args.data, {
-                ref: args.ref,
-                context: createFormContext,
-                $item: $newItem,
-                $form: args.$form
-              });
+        if (preFilter != null)
+            hiddenFields = preFilter();
+
+        $.each(fields, function(key) {
+            if ($.inArray(key, hiddenFields) != -1)
+                return true;
+            var field = this;
+            var $th = $('<th>').addClass(key).appendTo($thead.find('tr'));
+
+            if ($th.index()) $th.addClass('reduced-hide');
+
+            $th.html(_l(field.label));
+
+            return true;
+        });
+
+        // Re-order row buttons
+        if (reorder) {
+            $thead.find('tr').append(
+                $('<th>').html(_l('label.order')).addClass('reorder-actions reduced-hide')
+            );
+        }
+
+        // Actions column
+        var actionsArray = actions ? $.map(actions, function(v, k) {
+            if (k == 'add') {
+                v.isAdd = true;
+            }
+
+            return v;
+        }) : [];
+        var headerActionsArray = $.grep(
+            actionsArray,
+            function(action) {
+                return action.isHeader || action.isAdd;
             }
-          });
+        );
+
+        if (actions && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) {
+            $thead.find('tr').append(
+                $('<th></th>')
+                .html(_l('label.actions'))
+                .addClass('actions reduced-hide')
+            );
         }
-      }
-    },
 
-    remove: function($instanceRow, args) {
-      uiActions.standard($instanceRow, args, {
-        complete: function(args, $newRow) {
-          $newRow.remove();
+        // Quick view
+        if (detailView && !$.isFunction(detailView) && !detailView.noCompact && !uiCustom) {
+            $thead.find('tr').append(
+                $('<th></th>')
+                .html(_l('label.quickview'))
+                .addClass('quick-view reduced-hide')
+            );
         }
-      });
-    },
-
-    edit: function($instanceRow, args) {
-      var $td = $instanceRow.find('td.editable');
-      var $edit = $td.find('div.edit');
-      var $editInput = $edit.find('input');
-      var $label = $td.find('span');
-      var $listView = $instanceRow.closest('.list-view');
-      var listViewArgs = $listView.data('view-args');
-
-      // Hide label, show edit field
-      var showEditField = function() {
-        $edit.css({ opacity: 1 });
-        $label.fadeOut('fast', function() {
-          $edit.fadeIn();
-          $editInput.focus();
-          $instanceRow.closest('div.data-table').dataTable('refresh');
+
+        return $thead;
+    };
+
+    var createFilters = function($toolbar, filters) {
+        if (!filters) return false;
+
+        var $filters = $('<div></div>').addClass('filters reduced-hide');
+        $filters.append($('<label>').html(_l('label.filterBy')));
+
+        var $filterSelect = $('<select id="filterBy"></select>').appendTo($filters);
+
+        if (filters)
+            $.each(filters, function(key) {
+                if (this.preFilter != null && this.preFilter() == false) {
+                    return true; //skip to next item in each loop
+                }
+                var $option = $('<option>').attr({
+                    value: key
+                }).html(_l(this.label));
+
+                $option.appendTo($filterSelect);
+
+                return true;
+            });
+
+        return $filters.appendTo($toolbar);
+    };
+
+    var createSearchBar = function($toolbar, listViewData) {
+        var $search = $('<div></div>').addClass('text-search reduced-hide');
+        var $searchBar = $('<div></div>').addClass('search-bar reduced hide').appendTo($search);
+        $searchBar.append('<input type="text" />');
+        $search.append('<div id="basic_search" class="button search"></div>');
+
+        if (listViewData.advSearchFields != null) {
+            $search.append(
+                $('<div>').attr({
+                    id: 'advanced_search'
+                })
+                .addClass('button search')
+                .append($('<div>').addClass('icon'))
+            );
+        }
+
+        return $search.appendTo($toolbar);
+    };
+
+    /**
+     * Makes set of icons from data, in the for of a table cell
+     */
+    var makeActionIcons = function($td, actions, options) {
+        options = options ? options : {};
+        var allowedActions = options.allowedActions;
+        var $tr = $td.closest('tr');
+        var data = $tr && $tr.data('json-obj') ? $tr.data('json-obj') : null;
+
+        $.each(actions, function(actionName, action) {
+            if (actionName == 'add' || action.isHeader)
+                return true;
+
+            if (action.type == 'radio') {
+                $td.append(
+                    $('<div></div>')
+                    .addClass('action')
+                    .addClass(actionName)
+                    .append(
+                        $('<input>').attr({
+                            type: 'radio',
+                            name: actionName
+                        })
+                    )
+                    .attr({
+                        alt: _l(action.label),
+                        title: _l(action.label)
+                    })
+                    .data('list-view-action-id', actionName)
+                );
+
+                return true;
+            } else if (action.type == 'checkbox') {
+                $td.append(
+                    $('<div></div>')
+                    .addClass('action')
+                    .addClass(actionName)
+                    .append(
+                        $('<input>').attr({
+                            type: 'checkbox',
+                            name: actionName,
+                            checked: data && data._isSelected ? 'checked' : false
+                        })
+                    )
+                    .attr({
+                        alt: _l(action.label),
+                        title: _l(action.label)
+                    })
+                    .data('list-view-action-id', actionName)
+                );
+
+                if ($td.find('input[type=checkbox]').is(':checked')) {
+                    $tr.addClass('multi-edit-selected');
+                }
+
+                return true;
+            }
+
+            var $action = $('<div></div>')
+                .addClass('action')
+                .addClass(actionName)
+                .append($('<span>').addClass('icon').html('&nbsp;'))
+                .attr({
+                    alt: _l(action.label),
+                    title: _l(action.label)
+                })
+                .data('list-view-action-id', actionName);
+
+            if (action.textLabel) {
+                $action
+                    .addClass('text')
+                    .prepend(
+                        $('<span>').addClass('label').html(_l(action.textLabel))
+                );
+            }
+
+            // Disabled appearance/behavior for filtered actions
+            if (allowedActions && $.inArray(actionName, allowedActions) == -1) {
+                $action.addClass('disabled');
+            }
+
+            $td.append($action);
+
+            return true;
+        });
+    };
+
+    /**
+     * Initialize detail view for specific ID from list view
+     */
+    var createDetailView = function(args, complete, $row, options) {
+        var $panel = args.$panel;
+        var title = args.title;
+        var id = args.id;
+        var data = $.extend(true, {}, args.data, {
+            $browser: $('#browser .container'),
+            id: id,
+            jsonObj: args.jsonObj,
+            section: args.section,
+            context: args.context,
+            $listViewRow: $row,
+            compact: options ? options.compact : false
         });
-      };
 
-      // Hide edit field, validate and save changes
-      var showLabel = function(val, options) {
+        var noPanel = options ? options.noPanel : false;
+        var $detailView, $detailsPanel;
+        var panelArgs = {
+            title: title,
+            parent: $panel,
+            maximizeIfSelected: data.isMaximized,
+            complete: function($newPanel) {
+                // Make detail view element
+                if (!args.pageGenerator && !data.isMaximized)
+                    $detailView = $('<div>').addClass('detail-view').detailView(data).appendTo($newPanel);
+                else if (!args.pageGenerator && data.isMaximized)
+                    $detailView = $newPanel.detailView(data);
+                else
+                    $detailView = args.pageGenerator(data).appendTo($newPanel);
+
+                if (complete) complete($detailView);
+
+                return $detailView;
+            }
+        };
+
+        if (noPanel) {
+            return $('<div>').detailView(data);
+        } else {
+            $detailsPanel = data.$browser.cloudBrowser('addPanel', panelArgs);
+        }
+    };
+
+    var addTableRows = function(preFilter, fields, data, $tbody, actions, options) {
         if (!options) options = {};
+        var rows = [];
+        var reorder = options.reorder;
+        var detailView = options.detailView;
+        var $listView = $tbody.closest('.list-view');
+        var listViewArgs = $listView.data('view-args');
+        var uiCustom = listViewArgs.uiCustom;
+        var subselect = uiCustom ? listViewArgs.listView.subselect : null;
+
+        if (!(data && data.length)) {
+            if (!$tbody.find('tr').size()) {
+                return [
+                    $('<tr>').addClass('empty last').append(
+                        $('<td>').html(_l('label.no.data'))
+                    ).appendTo($tbody)
+                ];
+            }
+        }
 
-        var oldVal = $label.html();
+        $tbody.find('tr.empty').remove();
 
-        if(val != null )
-          $label.html(_s(val));
+        $(data).each(function() {
+            var dataItem = this;
+            var id = dataItem.id;
+            var $quickView;
 
-        var data = {
-          id: $instanceRow.data('list-view-item-id'),
-          jsonObj: $instanceRow.data('jsonObj')
-        };
+            var $tr = $('<tr>');
+            rows.push($tr);
 
-        data[$td.data('list-view-item-field')] = $editInput.val();
+            if (options.prepend) {
+                $tr.prependTo($tbody);
+            } else {
+                $tr.appendTo($tbody);
+            }
 
-        var context = $.extend({}, listViewArgs.context);
-        context[
-          listViewArgs.activeSection
-        ] = $instanceRow.data('jsonObj');
+            var hiddenFields = [];
+            if (preFilter != null)
+                hiddenFields = preFilter();
+
+            // Add field data
+            $.each(fields, function(key) {
+                if ($.inArray(key, hiddenFields) != -1)
+                    return true;
+                var field = this;
+                var $td = $('<td>')
+                    .addClass(key)
+                    .data('list-view-item-field', key)
+                    .appendTo($tr);
+                var content = dataItem[key];
+
+                if (field.truncate) {
+                    $td.addClass('truncated');
+                }
 
-        args.callback({
-          data: data,
-          context: context,
-          response: {
-            success: function(args) {
-              $edit.hide();
-              $label.fadeIn();
-              $instanceRow.closest('div.data-table').dataTable('refresh');
+                if (field.indicator) {
+                    $td.addClass('state').addClass(field.indicator[content]);
 
-              if (options.success) options.success(args);
-            },
-            error: function(message) {
-              if (message) {
-                cloudStack.dialog.notice({ message: message });
-                $edit.hide(),
-                $label.html(_s(oldVal)).fadeIn();
-                $instanceRow.closest('div.data-table').dataTable('refresh');
+                    // Disabling indicator for now per new design
+                    //$tr.find('td:first').addClass('item-state-' + field.indicator[content]);
+                }
 
-                if (options.error) options.error(args);
-              }
+                if (field.id == true) id = field.id;
+                if ($td.index()) $td.addClass('reduced-hide');
+                if (field.action) {
+                    $td.data('list-view-action', key);
+                }
+                if (field.converter) {
+                    content = _l(field.converter(content, dataItem));
+                }
+                if (field.editable) {
+                    $td.html(_s(content));
+                    createEditField($td).appendTo($td);
+                } else {
+                    $td.html('');
+                    $td.append(
+                        $('<span></span>').html(_s(content))
+                    );
+                }
+
+                $td.attr('title', _s(content));
+            });
+
+            $tr.find('td:first').addClass('first');
+
+            // Add reorder actions
+            if (reorder) {
+                var sort = function($tr, action) {
+                    var $listView = $tr.closest('.list-view');
+                    var viewArgs = $listView.data('view-args');
+                    var context = $.extend(
+                        true, {},
+                        $tr.closest('.list-view').data('view-args').context
+                    );
+                    var rowIndex = $tr.closest('tbody').find('tr').size() - ($tr.index());
+
+                    context[viewArgs.activeSection] = $tr.data('json-obj');
+
+                    action.action({
+                        context: context,
+                        index: rowIndex,
+                        response: {
+                            success: function(args) {},
+                            error: function(args) {
+                                // Move back to previous position
+                                rowActions.moveTo($tr, rowIndex);
+                            }
+                        }
+                    });
+                };
+
+                $('<td>').addClass('actions reorder').appendTo($tr).append(function() {
+                    var $td = $(this);
+
+                    $.each(reorder, function(actionName, action) {
+                        var fnLabel = {
+                            moveTop: _l('label.move.to.top'),
+                            moveBottom: _l('label.move.to.bottom'),
+                            moveUp: _l('label.move.up.row'),
+                            moveDown: _l('label.move.down.row'),
+                            moveDrag: _l('label.drag.new.position')
+                        };
+
+                        $('<div>')
+                            .addClass('action reorder')
+                            .addClass(actionName)
+                            .append(
+                                $('<span>').addClass('icon').html('&nbsp;')
+                        )
+                            .attr({
+                                title: _l(fnLabel[actionName])
+                            })
+                            .appendTo($td)
+                            .click(function() {
+                                if (actionName == 'moveDrag') return false;
+
+                                rowActions[actionName]($tr);
+                                $tr.closest('tbody').find('tr').each(function() {
+                                    sort($(this), action);
+                                });
+                                $tr.closest('.data-table').dataTable('selectRow', $tr.index());
+
+                                return false;
+                            });
+                    });
+                });
+
+                // Draggable action
+                var initDraggable = function($tr) {
+                    var originalIndex;
+
+                    return $tr.closest('tbody').sortable({
+                        handle: '.action.moveDrag',
+                        start: function(event, ui) {
+                            originalIndex = ui.item.index();
+                        },
+                        stop: function(event, ui) {
+                            rowActions._std($tr, function() {});
+
+                            $tr.closest('tbody').find('tr').each(function() {
+                                sort($(this), reorder.moveDrag);
+                            });
+                        }
+                    });
+                };
+
+                if (reorder && reorder.moveDrag) {
+                    initDraggable($tr);
+                }
             }
-          }
-        });
-      };
-
-      if (args.cancel) {  //click Cancel button
-       // showLabel();
-         var oldVal = $label.html();
-         $edit.hide();
-         $label.fadeIn();
-         $instanceRow.closest('div.data-table').dataTable('refresh');
-         $editInput.val(_s(oldVal));
-        return false;
-      }
-
-      if (!$editInput.is(':visible') || !(typeof(args.action) == 'undefined')) { //click Edit button
-        showEditField();
-      }
-      else if ($editInput.val() != $label.html()) { //click Save button with changed value
-        $edit.animate({ opacity: 0.5 });
-
-        var originalName = $label.html();
-        var newName = $editInput.val();
-        showLabel(newName, {
-          success: function() {
-            cloudStack.ui.notifications.add(
-              {
-                section: $instanceRow.closest('div.view').data('view-args').id,
-                desc: newName ?
-                  _l('Set value of') +
-                  ' ' + $instanceRow.find('td.name span').html() +
-                  ' ' + _l('to') +
-                  ' ' + _s(newName) :
-                  _l('Unset value for') +
-                  ' ' + $instanceRow.find('td.name span').html()
-              },
-              function(args) {},
-              [{ name: newName }]
+
+            // Add action data
+            $tr.data('list-view-item-id', id);
+            $tr.data('jsonObj', dataItem);
+            $tr.data('list-view-action-filter', options.actionFilter);
+
+            var actionsArray = actions ? $.map(actions, function(v, k) {
+                if (k == 'add') {
+                    v.isAdd = true;
+                }
+
+                return v;
+            }) : [];
+            var headerActionsArray = $.grep(
+                actionsArray,
+                function(action) {
+                    return action.isHeader || action.isAdd;
+                }
             );
-          }
-        });
-      }
-      else {  //click Save button with unchanged value
-        showLabel();
-      }
-
-      return $instanceRow;
-    }
-  };
-
-  var rowActions = {
-    _std: function($tr, action) {
-      action();
-
-      $tr.closest('.data-table').dataTable('refresh');
-
-      setTimeout(function() {
-        $tr.closest('.data-table').dataTable('selectRow', $tr.index());
-      }, 0);
-    },
-
-    moveTop: function($tr) {
-      rowActions._std($tr, function() {
-        $tr.closest('tbody').prepend($tr);
-        $tr.closest('.list-view').animate({ scrollTop: 0 });
-      });
-    },
-
-    moveBottom: function($tr) {
-      rowActions._std($tr, function() {
-        $tr.closest('tbody').append($tr);
-        $tr.closest('.list-view').animate({ scrollTop: 0 });
-      });
-    },
-
-    moveUp: function($tr) {
-      rowActions._std($tr, function() {
-        $tr.prev().before($tr);
-      });
-    },
-
-    moveDown: function($tr) {
-      rowActions._std($tr, function() {
-        $tr.next().after($tr);
-      });
-    },
-
-    moveTo: function($tr, index, after) {
-      rowActions._std($tr, function() {
-        var $target = $tr.closest('tbody').find('tr').filter(function() {
-          return $(this).index() == index;
-        });
 
-    //    if ($target.index() > $tr.index()) $target.after($tr);
-      //  else $target.before($tr);
-
-        $tr.closest('.list-view').scrollTop($tr.position().top - $tr.height() * 2);
-
-        if (after)
-          setTimeout(function() {
-            after();
-          });
-      });
-    }
-  };
-
-  /**
-   * Edit field text
-   *
-   * @param $td {jQuery} <td> to put input field into
-   */
-  var createEditField = function($td) {
-    $td.addClass('editable');
-
-    // Put <td> label into a span
-    var sanitizedValue = $td.html();
-    $('<span></span>').html(sanitizedValue).appendTo($td.html(''));
-
-    var $editArea = $('<div></div>').addClass('edit');
-    var $editField = $('<input />').addClass('edit').attr({
-      type: 'text',
-      value: cloudStack.sanitizeReverse(sanitizedValue)
-    });
-    var $actionButton = $('<div></div>').addClass('action');
-    var $saveButton = $actionButton.clone().addClass('save').attr({
-      'title': _l('Save')
-    });
-    var $cancelButton = $actionButton.clone().addClass('cancel').attr({
-      'title': _l('Cancel edit')
-    });
+            if (actions && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) {
+                var allowedActions = $.map(actions, function(value, key) {
+                    return key;
+                });
 
-    $([$editField, $saveButton, $cancelButton]).each(function() {
-      this.appendTo($editArea);
-    });
+                var $listView = $tr.closest('.list-view');
+                var isUICustom = $listView.data('view-args') ?
+                    $tr.closest('.list-view').data('view-args').uiCustom : false;
 
-    return $editArea.hide();
-  };
-
-  var renderActionCol = function(actions) {
-    return $.grep(
-      $.map(actions, function(value, key) {
-        return key;
-      }),
-      function(elem) { return elem != 'add'; }
-    ).length;
-  };
-
-  var createHeader = function(preFilter, fields, $table, actions, options) {
-    if (!options) options = {};
-
-    var $thead = $('<thead>').prependTo($table).append($('<tr>'));
-    var reorder = options.reorder;
-    var detailView = options.detailView;
-    var viewArgs = $table.closest('.list-view').data('view-args');
-    var uiCustom = viewArgs.uiCustom;
-    var hiddenFields = [];
-    
-    if (preFilter != null)
-      hiddenFields = preFilter();
-
-    $.each(fields, function(key) {
-      if($.inArray(key, hiddenFields) != -1)
-        return true;
-      var field = this;
-      var $th = $('<th>').addClass(key).appendTo($thead.find('tr'));
-
-      if ($th.index()) $th.addClass('reduced-hide');
-
-      $th.html(_l(field.label));
-
-      return true;
-    });
+                if ($.isFunction(options.actionFilter) && !isUICustom) {
+                    allowedActions = options.actionFilter({
+                        context: $.extend(true, {}, options.context, {
+                            actions: allowedActions,
+                            item: dataItem
+                        })
+                    });
+                }
 
-    // Re-order row buttons
-    if (reorder) {
-      $thead.find('tr').append(
-        $('<th>').html(_l('label.order')).addClass('reorder-actions reduced-hide')
-      );
-    }
-
-    // Actions column
-    var actionsArray = actions ? $.map(actions, function(v, k) {
-      if (k == 'add') {
-        v.isAdd = true;
-      }
-
-      return v;
-    }) : [];
-    var headerActionsArray = $.grep(
-      actionsArray,
-      function(action) {
-        return action.isHeader || action.isAdd;
-      }
-    );
-
-    if (actions && renderActionCol(actions) && actionsArray.length != headerActionsArray.length) {
-      $thead.find('tr').append(
-        $('<th></th>')
-          .html(_l('label.actions'))
-          .addClass('actions reduced-hide')
-      );
-    }
-
-    // Quick view
-    if (detailView &&
-        !$.isFunction(detailView) &&
-        !detailView.noCompact && !uiCustom) {
-      $thead.find('tr').append(
-        $('<th></th>')
-          .html(_l('label.quickview'))
-          .addClass('quick-view reduced-hide')
-      );
-    }
-
-    return $thead;
-  };
-
-  var createFilters = function($toolbar, filters) {
-    if (!filters) return false;
-
-      var $filters = $('<div></div>').addClass('filters reduced-hide');
-      $filters.append($('<label>').html(_l('label.filterBy')));
-
-      var $filterSelect = $('<select id="filterBy"></select>').appendTo($filters);
-
-      if (filters)
-        $.each(filters, function(key) {
-          if(this.preFilter != null && this.preFilter() == false) {
-            return true; //skip to next item in each loop
-          }
-          var $option = $('<option>').attr({
-            value: key
-          }).html(_l(this.label));
-
-          $option.appendTo($filterSelect);
-
-          return true;
+                makeActionIcons(
+                    $('<td></td>').addClass('actions reduced-hide')
+                    .appendTo($tr),
+                    actions, {
+                        allowedActions: allowedActions
+                    }
+                );
+
+                $listView.trigger('cloudStack.listView.addRow', {
+                    $tr: $tr
+                });
+            }
+
+            // Add sub-select
+            if (subselect) {
+                var $td = $tr.find('td.first');
+                var $select = $('<div></div>').addClass('subselect').append(
+                    $('<span>').html(_l(subselect.label)),
+                    $('<select>')
+                ).hide();
+                var $selectionArea = $tr.find('td:last').find('input');
+
+                $td.append($select);
+
+                // Show and populate selection
+                $selectionArea.change(function() {
+                    if ($(this).is(':checked')) {
+                        // Populate data
+                        subselect.dataProvider({
+                            context: $.extend(true, {}, options.context, {
+                                instances: [$tr.data('json-obj')]
+                            }),
+                            response: {
+                                success: function(args) {
+                                    var data = args.data;
+
+                                    if (data.length) {
+                                        $(data).map(function(index, item) {
+                                            var $option = $('<option>');
+
+                                            $option.attr('value', item.id);
+                                            $option.append(item.description);
+                                            $option.appendTo($select.find('select'));
+                                        });
+                                        $select.show();
+                                    } else {
+                                        $select.hide();
+                                    }
+
+                                    $listView.find('.data-table').dataTable('refresh');
+                                }
+                            }
+                        });
+
+                        if ($(this).is('input[type=radio]')) {
+                            $(this).closest('tr').siblings().find('input[type=radio]').change();
+                        }
+                    } else {
+                        $select.find('option').remove();
+                        $select.hide();
+                    }
+                });
+            }
+
+            // Add quick view
+            if (detailView && !$.isFunction(detailView) && !detailView.noCompact && !uiCustom) {
+                $quickView = $('<td>').addClass('quick-view reduced-hide')
+                    .append(
+                        $('<span>').addClass('icon').html('&nbsp;')
+                )
+                    .appendTo($tr);
+                $quickView.mouseover(
+                    // Show quick view
+
+                    function() {
+                        var $quickViewTooltip = $('<div>').addClass('quick-view-tooltip hovered-elem');
+                        var $tr = $quickView.closest('tr');
+                        var $listView = $tr.closest('.list-view');
+                        var $title = $('<div>').addClass('title');
+                        var $detailsContainer = $('<div>').addClass('container').appendTo($quickViewTooltip);
+                        var context = $.extend(true, {}, $listView.data('view-args').context);
+                        var activeSection = $listView.data('view-args').activeSection;
+                        var itemID = $tr.data('list-view-item-id');
+                        var jsonObj = $tr.data('json-obj');
+                        var $loading = $('<div>').addClass('loading-overlay').appendTo($detailsContainer);
+
+                        if ($tr.hasClass('loading')) return;
+
+                        // Title
+                        $title.append(
+                            $('<span>').html(_l('label.quickview') + ': '),
+                            $('<span>').addClass('title').html(
+                                cloudStack.concat(
+                                    $tr.find('td:first span').html(), 30
+                                )
+                            ).attr({
+                                title: $tr.find('td:first span').html()
+                            }),
+                            $('<span>').addClass('icon').html('&nbsp;')
+                        );
+                        $quickViewTooltip.append($title);
+                        $('.quick-view-tooltip').remove();
+                        // Setup positioning
+                        $quickViewTooltip.hide().appendTo('#container').fadeIn(200, function() {
+                            if (!$quickViewTooltip.is(':visible')) return;
+
+                            // Init detail view
+                            context[activeSection] = [jsonObj];
+                            createDetailView({
+                                    data: $.extend(true, {}, detailView, {
+                                        onLoad: function($detailView) {
+                                            $loading.remove();
+                                            $detailView.slideToggle('fast');
+                                        },
+                                        onPerformAction: function() {
+                                            $tr.addClass('loading').find('td:last').prepend($('<div>').addClass('loading'));
+                                            $quickViewTooltip.hide();
+                                        },
+                                        onActionComplete: function() {
+                                            if (listViewArgs.onActionComplete) {
+                                                listViewArgs.onActionComplete();
+                                            }
+
+                                            $tr.removeClass('loading').find('td:last .loading').remove();
+                                            $quickViewTooltip.remove();
+                                        }
+                                    }),
+                                    id: itemID,
+                                    jsonObj: jsonObj,
+                                    section: activeSection,
+                                    context: context,
+                                    $listViewRow: $tr
+                                },
+                                function($detailView) { //complete(), callback funcion
+                                    $detailView.data('list-view', $listView);
+                                }, $tr, {
+                                    compact: true,
+                                    noPanel: true
+                                }
+                            ).appendTo($detailsContainer).hide();
+                        });
+                        $quickViewTooltip.css({
+                            position: 'absolute',
+                            left: $tr.width() + ($quickViewTooltip.width() -
+                                ($quickViewTooltip.width() / 2)),
+                            top: $quickView.offset().top - 50,
+                            zIndex: $tr.closest('.panel').zIndex() + 1
+                        });
+
+                        $quickViewTooltip.mouseleave(function() {
+                            if (!$('.overlay:visible').size()) {
+                                $quickViewTooltip.remove();
+                            }
+                        });
+                    }
+                );
+            }
         });
 
-        return $filters.appendTo($toolbar);
-  };
-
-  var createSearchBar = function($toolbar, listViewData) {
-    var $search = $('<div></div>').addClass('text-search reduced-hide');
-    var $searchBar = $('<div></div>').addClass('search-bar reduced hide').appendTo($search);
-    $searchBar.append('<input type="text" />');
-    $search.append('<div id="basic_search" class="button search"></div>');
-
-    if (listViewData.advSearchFields != null) {
-      $search.append(
-        $('<div>').attr({
-        id: 'advanced_search'
-      })
-      .addClass('button search')
-      .append($('<div>').addClass('icon'))
-      );
-    }
-
-    return $search.appendTo($toolbar);
-  }; 
-
-  /**
-   * Makes set of icons from data, in the for of a table cell
-   */
-  var makeActionIcons = function($td, actions, options) {
-    options = options ? options : {};
-    var allowedActions = options.allowedActions;
-    var $tr = $td.closest('tr');
-    var data = $tr && $tr.data('json-obj') ? $tr.data('json-obj') : null;
-
-    $.each(actions, function(actionName, action) {
-      if (actionName == 'add' || action.isHeader)
-        return true;
-
-      if (action.type == 'radio') {
-        $td.append(
-          $('<div></div>')
-            .addClass('action')
-            .addClass(actionName)
-            .append(
-              $('<input>').attr({
-                type: 'radio',
-                name: actionName
-              })
-            )
-            .attr({
-              alt: _l(action.label),
-              title: _l(action.label)
-            })
-            .data('list-view-action-id', actionName)
-        );
+        return rows;
+    };
 
-        return true;
-      } else if (action.type == 'checkbox') {
-        $td.append(
-          $('<div></div>')
-            .addClass('action')
-            .addClass(actionName)
+    var setLoading = function($table, completeFn) {
+        var $loading = $('<tr>')
+            .addClass('loading')
+            .appendTo($table.find('tbody'))
             .append(
-              $('<input>').attr({
-                type: 'checkbox',
-                name: actionName,
-                checked: data && data._isSelected ?
-                  'checked' : false
-              })
-            )
-            .attr({
-              alt: _l(action.label),
-              title: _l(action.label)
-            })
-            .data('list-view-action-id', actionName)
+                $('<td>')
+                .addClass('loading icon')
+                .attr({
+                    'colspan': $table.find('th').size()
+                })
         );
 
-        if ($td.find('input[type=checkbox]').is(':checked')) {
-          $tr.addClass('multi-edit-selected');
+        $table.closest('div.list-view').scrollTop($table.height() + 100);
+
+        return completeFn({
+            loadingCompleted: function() {
+                $loading.remove();
+            }
+        });
+    };
+
+    var loadBody = function($table, dataProvider, preFilter, fields, append, loadArgs, actions, options) {
+        if (!options) options = {};
+        var context = options.context;
+        var reorder = options.reorder;
+        var $tbody = $table.find('tbody');
+
+        if (!loadArgs) loadArgs = {
+            page: 1,
+            filterBy: {
+                search: {},
+                kind: 'all',
+                page: 1
+            }
+        };
+
+        if (!append) {
+            if (!append) $table.find('tbody tr').remove();
         }
 
-        return true;
-      }
-
-      var $action = $('<div></div>')
-            .addClass('action')
-            .addClass(actionName)
-            .append($('<span>').addClass('icon').html('&nbsp;'))
-            .attr({
-              alt: _l(action.label),
-              title: _l(action.label)
-            })
-            .data('list-view-action-id', actionName);
-
-      if (action.textLabel) {
-        $action
-          .addClass('text')
-          .prepend(
-            $('<span>').addClass('label').html(_l(action.textLabel))
-          );
-      }
-
-      // Disabled appearance/behavior for filtered actions
-      if (allowedActions && $.inArray(actionName, allowedActions) == -1) {
-        $action.addClass('disabled');
-      }
-
-      $td.append($action);
-
-      return true;
-    });
-  };
-
-  /**
-   * Initialize detail view for specific ID from list view
-   */
-  var createDetailView = function(args, complete, $row, options) {
-    var $panel = args.$panel;
-    var title = args.title;
-    var id = args.id;
-    var data = $.extend(true, {}, args.data, {
-      $browser: $('#browser .container'),
-      id: id,
-      jsonObj: args.jsonObj,
-      section: args.section,
-      context: args.context,
-      $listViewRow: $row,
-      compact: options ? options.compact : false
-    });
+        var viewArgs = $table.closest('.list-view').data('view-args');
+        var uiCustom = viewArgs.listView ? viewArgs.listView.uiCustom : false;
+
+        setLoading($table, function(setLoadingArgs) {
+            $table.dataTable();
+            $.extend(loadArgs, {
+                context: options.context,
+                response: {
+                    success: function(args) {
+                        setLoadingArgs.loadingCompleted();
+
+                        addTableRows(preFilter, fields, args.data, $tbody, actions, {
+                            actionFilter: args.actionFilter,
+                            context: context,
+                            reorder: reorder,
+                            detailView: options.detailView
+                        });
+                        $table.dataTable(null, {
+                            noSelect: uiCustom
+                        });
+
+                        if (args.data &&
+                            args.data.length < pageSize &&
+                            options.setEndTable) {
+                            options.setEndTable();
+                        }
 
-    var noPanel = options ? options.noPanel : false;
-    var $detailView, $detailsPanel;
-    var panelArgs = {
-      title: title,
-      parent: $panel,
-      maximizeIfSelected: data.isMaximized,
-      complete: function($newPanel) {
-        // Make detail view element
-        if (!args.pageGenerator && !data.isMaximized)
-          $detailView = $('<div>').addClass('detail-view').detailView(data).appendTo($newPanel);
-        else if (!args.pageGenerator && data.isMaximized)
-          $detailView = $newPanel.detailView(data);
-        else
-          $detailView = args.pageGenerator(data).appendTo($newPanel);
-
-        if (complete) complete($detailView);
-
-        return $detailView;
-      }
+                        setTimeout(function() {
+                            $table.dataTable('refresh');
+                        });
+                    },
+                    error: function(args) {
+                        setLoadingArgs.loadingCompleted();
+                        addTableRows(preFilter, fields, [], $tbody, actions);
+                        $table.find('td:first').html(_l('ERROR'));
+                        $table.dataTable(null, {
+                            noSelect: uiCustom
+                        });
+                    }
+                }
+            });
+        });
+
+        return dataProvider(loadArgs);
     };
 
-    if (noPanel) {
-      return $('<div>').detailView(data);
-    } else {
-      $detailsPanel = data.$browser.cloudBrowser('addPanel', panelArgs);
-    }
-  };
-
-  var addTableRows = function(preFilter, fields, data, $tbody, actions, options) {
-    if (!options) options = {};
-    var rows = [];
-    var reorder = options.reorder;
-    var detailView = options.detailView;
-    var $listView = $tbody.closest('.list-view');
-    var listViewArgs = $listView.data('view-args');
-    var uiCustom = listViewArgs.uiCustom;
-    var subselect = uiCustom ? listViewArgs.listView.subselect : null;
-
-    if (!(data && data.length)) {
-      if (!$tbody.find('tr').size()) {
-        return [
-          $('<tr>').addClass('empty last').append(
-            $('<td>').html(_l('label.no.data'))
-          ).appendTo($tbody)
-        ];
-      }
-    }
-
-    $tbody.find('tr.empty').remove();
-
-    $(data).each(function() {
-      var dataItem = this;
-      var id = dataItem.id;
-      var $quickView;
-
-      var $tr = $('<tr>');
-      rows.push($tr);
-
-      if (options.prepend) {
-        $tr.prependTo($tbody);
-      } else {
-        $tr.appendTo($tbody);
-      }
-
-      var hiddenFields = [];
-      if(preFilter != null)
-        hiddenFields = preFilter();
-
-      // Add field data
-      $.each(fields, function(key) {
-        if($.inArray(key, hiddenFields) != -1)
-          return true;
-        var field = this;
-        var $td = $('<td>')
-              .addClass(key)
-              .data('list-view-item-field', key)
-              .appendTo($tr);
-        var content = dataItem[key];
-
-        if (field.truncate) {
-          $td.addClass('truncated');
-        }
+    /**
+     * Make 'switcher' buttons for sections
+     */
+    var createSectionSwitcher = function(args) {
+        var sections = args.sections;
+        var $switcher = $('<div>').addClass('section-switcher reduced-hide');
+        var $sectionSelect = $('<select></select>')
+            .appendTo(
+                $('<div></div>')
+                .addClass('section-select')
+                .appendTo($switcher)
+        );
+        var sectionPreFilter;
 
-        if (field.indicator) {
-          $td.addClass('state').addClass(field.indicator[content]);
+        if (args.sectionSelect) {
+            $('<label>')
+                .prependTo($sectionSelect.parent())
+                .html(_l(args.sectionSelect.label) + ':');
 
-          // Disabling indicator for now per new design
-          //$tr.find('td:first').addClass('item-state-' + field.indicator[content]);
-        }
-        
-        if (field.id == true) id = field.id;
-        if ($td.index()) $td.addClass('reduced-hide');
-        if (field.action) {
-          $td.data('list-view-action', key);
-        }
-        if (field.converter) {
-          content = _l(field.converter(content, dataItem));
-        }
-        if (field.editable) {
-          $td.html(_s(content));
-          createEditField($td).appendTo($td);
+            sectionPreFilter = args.sectionSelect.preFilter ?
+                args.sectionSelect.preFilter({
+                    context: cloudStack.context
+                }) : null;
+        } else {
+            $sectionSelect.hide();
         }
-        else {
-          $td.html('');
-          $td.append(
-            $('<span></span>').html(_s(content))
-          );
+
+        // No need to display switcher if only one entry is present
+        if (sectionPreFilter && sectionPreFilter.length == 1) {
+            $switcher.find('select').hide();
+            $switcher.find('label').html(
+                _l('label.viewing') + ' ' + _l(sections[sectionPreFilter[0]].title)
+            );
         }
-        
-        $td.attr('title', _s(content));
-      });
-
-      $tr.find('td:first').addClass('first');
-
-      // Add reorder actions
-      if (reorder) {
-        var sort = function($tr, action) {
-          var $listView = $tr.closest('.list-view');
-          var viewArgs = $listView.data('view-args');
-          var context = $.extend(
-            true, {},
-            $tr.closest('.list-view').data('view-args').context
-          );
-          var rowIndex = $tr.closest('tbody').find('tr').size() - ($tr.index());
-
-          context[viewArgs.activeSection] = $tr.data('json-obj');
-
-          action.action({
-            context: context,
-            index: rowIndex,
-            response: {
-              success: function(args) {},
-              error: function(args) {
-                // Move back to previous position
-                rowActions.moveTo($tr, rowIndex);
-              }
-            }
-          });
-        };
 
-        $('<td>').addClass('actions reorder').appendTo($tr).append(function() {
-          var $td = $(this);
+        $.each(sections, function(key) {
+            if (sectionPreFilter && $.inArray(key, sectionPreFilter) == -1) {
+                return true;
+            }
 
-          $.each(reorder, function(actionName, action) {
-            var fnLabel = {
-              moveTop: _l('label.move.to.top'),
-              moveBottom: _l('label.move.to.bottom'),
-              moveUp: _l('label.move.up.row'),
-              moveDown: _l('label.move.down.row'),
-              moveDrag: _l('label.drag.new.position')
-            };
+            var $sectionButton;
+
+            if (!this.type || this.type == 'button') {
+                $sectionButton = $('<div>')
+                    .addClass('section')
+                    .append(
+                        $('<a>')
+                        .addClass(key)
+                        .attr({
+                            href: '#'
+                        })
+                        .data('list-view-section-id', key)
+                        .html(_l(this.title))
+                );
 
-            $('<div>')
-              .addClass('action reorder')
-              .addClass(actionName)
-              .append(
-                $('<span>').addClass('icon').html('&nbsp;')
-              )
-              .attr({
-                title: _l(fnLabel[actionName])
-              })
-              .appendTo($td)
-              .click(function() {
-                if (actionName == 'moveDrag') return false;
-
-                rowActions[actionName]($tr);
-                $tr.closest('tbody').find('tr').each(function() {
-                  sort($(this), action);
-                });
-                $tr.closest('.data-table').dataTable('selectRow', $tr.index());
+                $sectionButton.appendTo($switcher);
+            } else if (this.type == 'select') {
+                $sectionSelect.append(
+                    $('<option></option>')
+                    .attr('value', key)
+                    .html(_l(thi

<TRUNCATED>

Mime
View raw message