whole_func_string: function InterimElementProvider() {
    InterimElementFactory.$inject = ["$document", "$q", "$rootScope", "$timeout", "$rootElement", "$animate", "$mdUtil", "$mdCompiler", "$mdTheming", "$injector", "$exceptionHandler"];
    createInterimElementProvider.$get = InterimElementFactory;
    return createInterimElementProvider;
  
    /**
     * Returns a new provider which allows configuration of a new interimElement
     * service. Allows configuration of default options & methods for options,
     * as well as configuration of 'preset' methods (eg dialog.basic(): basic is a preset method)
     */
    function createInterimElementProvider(interimFactoryName) {
      factory.$inject = ["$$interimElement", "$injector"];
      var EXPOSED_METHODS = ['onHide', 'onShow', 'onRemove'];
  
      var customMethods = {};
      var providerConfig = {
        presets: {}
      };
  
      var provider = {
        setDefaults: setDefaults,
        addPreset: addPreset,
        addMethod: addMethod,
        $get: factory
      };
  
      /**
       * all interim elements will come with the 'build' preset
       */
      provider.addPreset('build', {
        methods: ['controller', 'controllerAs', 'resolve', 'multiple',
          'template', 'templateUrl', 'themable', 'transformTemplate', 'parent', 'contentElement']
      });
  
      return provider;
  
      /**
       * Save the configured defaults to be used when the factory is instantiated
       */
      function setDefaults(definition) {
        providerConfig.optionsFactory = definition.options;
        providerConfig.methods = (definition.methods || []).concat(EXPOSED_METHODS);
        return provider;
      }
  
      /**
       * Add a method to the factory that isn't specific to any interim element operations
       */
  
      function addMethod(name, fn) {
        customMethods[name] = fn;
        return provider;
      }
  
      /**
       * Save the configured preset to be used when the factory is instantiated
       */
      function addPreset(name, definition) {
        definition = definition || {};
        definition.methods = definition.methods || [];
        definition.options = definition.options || function() { return {}; };
  
        if (/^cancel|hide|show$/.test(name)) {
          throw new Error("Preset '" + name + "' in " + interimFactoryName + " is reserved!");
        }
        if (definition.methods.indexOf('_options') > -1) {
          throw new Error("Method '_options' in " + interimFactoryName + " is reserved!");
        }
        providerConfig.presets[name] = {
          methods: definition.methods.concat(EXPOSED_METHODS),
          optionsFactory: definition.options,
          argOption: definition.argOption
        };
        return provider;
      }
  
      function addPresetMethod(presetName, methodName, method) {
        providerConfig.presets[presetName][methodName] = method;
      }
  
      /**
       * Create a factory that has the given methods & defaults implementing interimElement
       */
      /* @ngInject */
      function factory($$interimElement, $injector) {
        var defaultMethods;
        var defaultOptions;
        var interimElementService = $$interimElement();
  
        /*
         * publicService is what the developer will be using.
         * It has methods hide(), cancel(), show(), build(), and any other
         * presets which were set during the config phase.
         */
        var publicService = {
          hide: interimElementService.hide,
          cancel: interimElementService.cancel,
          show: showInterimElement,
  
          // Special internal method to destroy an interim element without animations
          // used when navigation changes causes a $scope.$destroy() action
          destroy : destroyInterimElement
        };
  
  
        defaultMethods = providerConfig.methods || [];
        // This must be invoked after the publicService is initialized
        defaultOptions = invokeFactory(providerConfig.optionsFactory, {});
  
        // Copy over the simple custom methods
        angular.forEach(customMethods, function(fn, name) {
          publicService[name] = fn;
        });
  
        angular.forEach(providerConfig.presets, function(definition, name) {
          var presetDefaults = invokeFactory(definition.optionsFactory, {});
          var presetMethods = (definition.methods || []).concat(defaultMethods);
  
          // Every interimElement built with a preset has a field called `$type`,
          // which matches the name of the preset.
          // Eg in preset 'confirm', options.$type === 'confirm'
          angular.extend(presetDefaults, { $type: name });
  
          // This creates a preset class which has setter methods for every
          // method given in the `.addPreset()` function, as well as every
          // method given in the `.setDefaults()` function.
          //
          // @example
          // .setDefaults({
          //   methods: ['hasBackdrop', 'clickOutsideToClose', 'escapeToClose', 'targetEvent'],
          //   options: dialogDefaultOptions
          // })
          // .addPreset('alert', {
          //   methods: ['title', 'ok'],
          //   options: alertDialogOptions
          // })
          //
          // Set values will be passed to the options when interimElement.show() is called.
          function Preset(opts) {
            this._options = angular.extend({}, presetDefaults, opts);
          }
          angular.forEach(presetMethods, function(name) {
            Preset.prototype[name] = function(value) {
              this._options[name] = value;
              return this;
            };
          });
  
          // Create shortcut method for one-linear methods
          if (definition.argOption) {
            var methodName = 'show' + name.charAt(0).toUpperCase() + name.slice(1);
            publicService[methodName] = function(arg) {
              var config = publicService[name](arg);
              return publicService.show(config);
            };
          }
  
          // eg $mdDialog.alert() will return a new alert preset
          publicService[name] = function(arg) {
            // If argOption is supplied, eg `argOption: 'content'`, then we assume
            // if the argument is not an options object then it is the `argOption` option.
            //
            // @example `$mdToast.simple('hello')` // sets options.content to hello
            //                                     // because argOption === 'content'
            if (arguments.length && definition.argOption &&
                !angular.isObject(arg) && !angular.isArray(arg))  {
  
              return (new Preset())[definition.argOption](arg);
  
            } else {
              return new Preset(arg);
            }
  
          };
        });
  
        return publicService;
  
        /**
         *
         */
        function showInterimElement(opts) {
          // opts is either a preset which stores its options on an _options field,
          // or just an object made up of options
          opts = opts || { };
          if (opts._options) opts = opts._options;
  
          return interimElementService.show(
            angular.extend({}, defaultOptions, opts)
          );
        }
  
        /**
         *  Special method to hide and destroy an interimElement WITHOUT
         *  any 'leave` or hide animations ( an immediate force hide/remove )
         *
         *  NOTE: This calls the onRemove() subclass method for each component...
         *  which must have code to respond to `options.$destroy == true`
         */
        function destroyInterimElement(opts) {
            return interimElementService.destroy(opts);
        }
  
        /**
         * Helper to call $injector.invoke with a local of the factory name for
         * this provider.
         * If an $mdDialog is providing options for a dialog and tries to inject
         * $mdDialog, a circular dependency error will happen.
         * We get around that by manually injecting $mdDialog as a local.
         */
        function invokeFactory(factory, defaultVal) {
          var locals = {};
          locals[interimFactoryName] = publicService;
          return $injector.invoke(factory || function() { return defaultVal; }, {}, locals);
        }
  
      }
  
    }
  
    /* @ngInject */
    function InterimElementFactory($document, $q, $rootScope, $timeout, $rootElement, $animate,
                                   $mdUtil, $mdCompiler, $mdTheming, $injector, $exceptionHandler) {
      return function createInterimElementService() {
        var SHOW_CANCELLED = false;
  
        /*
         * @ngdoc service
         * @name $$interimElement.$service
         *
         * @description
         * A service used to control inserting and removing an element into the DOM.
         *
         */
  
        var service;
  
        var showPromises = []; // Promises for the interim's which are currently opening.
        var hidePromises = []; // Promises for the interim's which are currently hiding.
        var showingInterims = []; // Interim elements which are currently showing up.
  
        // Publish instance $$interimElement service;
        // ... used as $mdDialog, $mdToast, $mdMenu, and $mdSelect
  
        return service = {
          show: show,
          hide: waitForInterim(hide),
          cancel: waitForInterim(cancel),
          destroy : destroy,
          $injector_: $injector
        };
  
        /*
         * @ngdoc method
         * @name $$interimElement.$service#show
         * @kind function
         *
         * @description
         * Adds the `$interimElement` to the DOM and returns a special promise that will be resolved or rejected
         * with hide or cancel, respectively. To external cancel/hide, developers should use the
         *
         * @param {*} options is hashMap of settings
         * @returns a Promise
         *
         */
        function show(options) {
          options = options || {};
          var interimElement = new InterimElement(options || {});
  
          // When an interim element is currently showing, we have to cancel it.
          // Just hiding it, will resolve the InterimElement's promise, the promise should be
          // rejected instead.
          var hideAction = options.multiple ? $q.resolve() : $q.all(showPromises);
  
          if (!options.multiple) {
            // Wait for all opening interim's to finish their transition.
            hideAction = hideAction.then(function() {
              // Wait for all closing and showing interim's to be completely closed.
              var promiseArray = hidePromises.concat(showingInterims.map(service.cancel));
              return $q.all(promiseArray);
            });
          }
  
          var showAction = hideAction.then(function() {
  
            return interimElement
              .show()
              .catch(function(reason) { return reason; })
              .finally(function() {
                showPromises.splice(showPromises.indexOf(showAction), 1);
                showingInterims.push(interimElement);
              });
  
          });
  
          showPromises.push(showAction);
  
          // In AngularJS 1.6+, exceptions inside promises will cause a rejection. We need to handle
          // the rejection and only log it if it's an error.
          interimElement.deferred.promise.catch(function(fault) {
            if (fault instanceof Error) {
              $exceptionHandler(fault);
            }
  
            return fault;
          });
  
          // Return a promise that will be resolved when the interim
          // element is hidden or cancelled...
          return interimElement.deferred.promise;
        }
  
        /*
         * @ngdoc method
         * @name $$interimElement.$service#hide
         * @kind function
         *
         * @description
         * Removes the `$interimElement` from the DOM and resolves the promise returned from `show`
         *
         * @param {*} resolveParam Data to resolve the promise with
         * @returns a Promise that will be resolved after the element has been removed.
         *
         */
        function hide(reason, options) {
          options = options || {};
  
          if (options.closeAll) {
            // We have to make a shallow copy of the array, because otherwise the map will break.
            return $q.all(showingInterims.slice().reverse().map(closeElement));
          } else if (options.closeTo !== undefined) {
            return $q.all(showingInterims.slice(options.closeTo).map(closeElement));
          }
  
          // Hide the latest showing interim element.
          return closeElement(showingInterims[showingInterims.length - 1]);
  
          function closeElement(interim) {
  
            var hideAction = interim
              .remove(reason, false, options || { })
              .catch(function(reason) { return reason; })
              .finally(function() {
                hidePromises.splice(hidePromises.indexOf(hideAction), 1);
              });
  
            showingInterims.splice(showingInterims.indexOf(interim), 1);
            hidePromises.push(hideAction);
  
            return interim.deferred.promise;
          }
        }
  
        /*
         * @ngdoc method
         * @name $$interimElement.$service#cancel
         * @kind function
         *
         * @description
         * Removes the `$interimElement` from the DOM and rejects the promise returned from `show`
         *
         * @param {*} reason Data to reject the promise with
         * @returns Promise that will be resolved after the element has been removed.
         *
         */
        function cancel(reason, options) {
          var interim = showingInterims.pop();
          if (!interim) {
            return $q.when(reason);
          }
  
          var cancelAction = interim
            .remove(reason, true, options || {})
            .catch(function(reason) { return reason; })
            .finally(function() {
              hidePromises.splice(hidePromises.indexOf(cancelAction), 1);
            });
  
          hidePromises.push(cancelAction);
  
          // Since AngularJS 1.6.7, promises will be logged to $exceptionHandler when the promise
          // is not handling the rejection. We create a pseudo catch handler, which will prevent the
          // promise from being logged to the $exceptionHandler.
          return interim.deferred.promise.catch(angular.noop);
        }
  
        /**
         * Creates a function to wait for at least one interim element to be available.
         * @param callbackFn Function to be used as callback
         * @returns {Function}
         */
        function waitForInterim(callbackFn) {
          return function() {
            var fnArguments = arguments;
  
            if (!showingInterims.length) {
              // When there are still interim's opening, then wait for the first interim element to
              // finish its open animation.
              if (showPromises.length) {
                return showPromises[0].finally(function () {
                  return callbackFn.apply(service, fnArguments);
                });
              }
  
              return $q.when("No interim elements currently showing up.");
            }
  
            return callbackFn.apply(service, fnArguments);
          };
        }
  
        /*
         * Special method to quick-remove the interim element without animations
         * Note: interim elements are in "interim containers"
         */
        function destroy(targetEl) {
          var interim = !targetEl ? showingInterims.shift() : null;
  
          var parentEl = angular.element(targetEl).length && angular.element(targetEl)[0].parentNode;
  
          if (parentEl) {
            // Try to find the interim in the stack which corresponds to the supplied DOM element.
            var filtered = showingInterims.filter(function(entry) {
              return entry.options.element[0] === parentEl;
            });
  
            // Note: This function might be called when the element already has been removed,
            // in which case we won't find any matches.
            if (filtered.length) {
              interim = filtered[0];
              showingInterims.splice(showingInterims.indexOf(interim), 1);
            }
          }
  
          return interim ? interim.remove(SHOW_CANCELLED, false, { '$destroy': true }) :
                           $q.when(SHOW_CANCELLED);
        }
  
        /*
         * Internal Interim Element Object
         * Used internally to manage the DOM element and related data
         */
        function InterimElement(options) {
          var self, element, showAction = $q.when(true);
  
          options = configureScopeAndTransitions(options);
  
          return self = {
            options : options,
            deferred: $q.defer(),
            show    : createAndTransitionIn,
            remove  : transitionOutAndRemove
          };
  
          /**
           * Compile, link, and show this interim element
           * Use optional autoHided and transition-in effects
           */
          function createAndTransitionIn() {
            return $q(function(resolve, reject) {
  
              // Trigger onCompiling callback before the compilation starts.
              // This is useful, when modifying options, which can be influenced by developers.
              options.onCompiling && options.onCompiling(options);
  
              compileElement(options)
                .then(function( compiledData ) {
                  element = linkElement( compiledData, options );
  
                  // Expose the cleanup function from the compiler.
                  options.cleanupElement = compiledData.cleanup;
  
                  showAction = showElement(element, options, compiledData.controller)
                    .then(resolve, rejectAll);
                }).catch(rejectAll);
  
              function rejectAll(fault) {
                // Force the '$md<xxx>.show()' promise to reject
                self.deferred.reject(fault);
  
                // Continue rejection propagation
                reject(fault);
              }
            });
          }
  
          /**
           * After the show process has finished/rejected:
           * - announce 'removing',
           * - perform the transition-out, and
           * - perform optional clean up scope.
           */
          function transitionOutAndRemove(response, isCancelled, opts) {
  
            // abort if the show() and compile failed
            if ( !element ) return $q.when(false);
  
            options = angular.extend(options || {}, opts || {});
            options.cancelAutoHide && options.cancelAutoHide();
            options.element.triggerHandler('$mdInterimElementRemove');
  
            if ( options.$destroy === true ) {
  
              return hideElement(options.element, options).then(function(){
                (isCancelled && rejectAll(response)) || resolveAll(response);
              });
  
            } else {
              $q.when(showAction).finally(function() {
                hideElement(options.element, options).then(function() {
                  isCancelled ? rejectAll(response) : resolveAll(response);
                }, rejectAll);
              });
  
              return self.deferred.promise;
            }
  
  
            /**
             * The `show()` returns a promise that will be resolved when the interim
             * element is hidden or cancelled...
             */
            function resolveAll(response) {
              self.deferred.resolve(response);
            }
  
            /**
             * Force the '$md<xxx>.show()' promise to reject
             */
            function rejectAll(fault) {
              self.deferred.reject(fault);
            }
          }
  
          /**
           * Prepare optional isolated scope and prepare $animate with default enter and leave
           * transitions for the new element instance.
           */
          function configureScopeAndTransitions(options) {
            options = options || { };
            if ( options.template ) {
              options.template = $mdUtil.processTemplate(options.template);
            }
  
            return angular.extend({
              preserveScope: false,
              cancelAutoHide : angular.noop,
              scope: options.scope || $rootScope.$new(options.isolateScope),
  
              /**
               * Default usage to enable $animate to transition-in; can be easily overridden via 'options'
               */
              onShow: function transitionIn(scope, element, options) {
                return $animate.enter(element, options.parent);
              },
  
              /**
               * Default usage to enable $animate to transition-out; can be easily overridden via 'options'
               */
              onRemove: function transitionOut(scope, element) {
                // Element could be undefined if a new element is shown before
                // the old one finishes compiling.
                return element && $animate.leave(element) || $q.when();
              }
            }, options );
  
          }
  
          /**
           * Compile an element with a templateUrl, controller, and locals
           */
          function compileElement(options) {
  
            var compiled = !options.skipCompile ? $mdCompiler.compile(options) : null;
  
            return compiled || $q(function (resolve) {
                resolve({
                  locals: {},
                  link: function () {
                    return options.element;
                  }
                });
              });
          }
  
          /**
           *  Link an element with compiled configuration
           */
          function linkElement(compileData, options){
            angular.extend(compileData.locals, options);
  
            var element = compileData.link(options.scope);
  
            // Search for parent at insertion time, if not specified
            options.element = element;
            options.parent = findParent(element, options);
            if (options.themable) $mdTheming(element);
  
            return element;
          }
  
          /**
           * Search for parent at insertion time, if not specified
           */
          function findParent(element, options) {
            var parent = options.parent;
  
            // Search for parent at insertion time, if not specified
            if (angular.isFunction(parent)) {
              parent = parent(options.scope, element, options);
            } else if (angular.isString(parent)) {
              parent = angular.element($document[0].querySelector(parent));
            } else {
              parent = angular.element(parent);
            }
  
            // If parent querySelector/getter function fails, or it's just null,
            // find a default.
            if (!(parent || {}).length) {
              var el;
              if ($rootElement[0] && $rootElement[0].querySelector) {
                el = $rootElement[0].querySelector(':not(svg) > body');
              }
              if (!el) el = $rootElement[0];
              if (el.nodeName == '#comment') {
                el = $document[0].body;
              }
              return angular.element(el);
            }
  
            return parent;
          }
  
          /**
           * If auto-hide is enabled, start timer and prepare cancel function
           */
          function startAutoHide() {
            var autoHideTimer, cancelAutoHide = angular.noop;
  
            if (options.hideDelay) {
              autoHideTimer = $timeout(service.hide, options.hideDelay) ;
              cancelAutoHide = function() {
                $timeout.cancel(autoHideTimer);
              };
            }
  
            // Cache for subsequent use
            options.cancelAutoHide = function() {
              cancelAutoHide();
              options.cancelAutoHide = undefined;
            };
          }
  
          /**
           * Show the element ( with transitions), notify complete and start
           * optional auto-Hide
           */
          function showElement(element, options, controller) {
            // Trigger onShowing callback before the `show()` starts
            var notifyShowing = options.onShowing || angular.noop;
            // Trigger onComplete callback when the `show()` finishes
            var notifyComplete = options.onComplete || angular.noop;
  
            // Necessary for consistency between AngularJS 1.5 and 1.6.
            try {
              notifyShowing(options.scope, element, options, controller);
            } catch (e) {
              return $q.reject(e);
            }
  
            return $q(function (resolve, reject) {
              try {
                // Start transitionIn
                $q.when(options.onShow(options.scope, element, options, controller))
                  .then(function () {
                    notifyComplete(options.scope, element, options);
                    startAutoHide();
  
                    resolve(element);
                  }, reject);
  
              } catch (e) {
                reject(e.message);
              }
            });
          }
  
          function hideElement(element, options) {
            var announceRemoving = options.onRemoving || angular.noop;
  
            return $q(function (resolve, reject) {
              try {
                // Start transitionIn
                var action = $q.when( options.onRemove(options.scope, element, options) || true );
  
                // Trigger callback *before* the remove operation starts
                announceRemoving(element, action);
  
                if (options.$destroy) {
                  // For $destroy, onRemove should be synchronous
                  resolve(element);
  
                  if (!options.preserveScope && options.scope ) {
                    // scope destroy should still be be done after the current digest is done
                    action.then( function() { options.scope.$destroy(); });
                  }
                } else {
                  // Wait until transition-out is done
                  action.then(function () {
                    if (!options.preserveScope && options.scope ) {
                      options.scope.$destroy();
                    }
  
                    resolve(element);
                  }, reject);
                }
              } catch (e) {
                reject(e.message);
              }
            });
          }
  
        }
      };
  
    }
  
  }
func_code_string: function InterimElementProvider() {
    InterimElementFactory.$inject = ["$document", "$q", "$rootScope", "$timeout", "$rootElement", "$animate", "$mdUtil", "$mdCompiler", "$mdTheming", "$injector", "$exceptionHandler"];
    createInterimElementProvider.$get = InterimElementFactory;
    return createInterimElementProvider;
  
    /**
     * Returns a new provider which allows configuration of a new interimElement
     * service. Allows configuration of default options & methods for options,
     * as well as configuration of 'preset' methods (eg dialog.basic(): basic is a preset method)
     */
    function createInterimElementProvider(interimFactoryName) {
      factory.$inject = ["$$interimElement", "$injector"];
      var EXPOSED_METHODS = ['onHide', 'onShow', 'onRemove'];
  
      var customMethods = {};
      var providerConfig = {
        presets: {}
      };
  
      var provider = {
        setDefaults: setDefaults,
        addPreset: addPreset,
        addMethod: addMethod,
        $get: factory
      };
  
      /**
       * all interim elements will come with the 'build' preset
       */
      provider.addPreset('build', {
        methods: ['controller', 'controllerAs', 'resolve', 'multiple',
          'template', 'templateUrl', 'themable', 'transformTemplate', 'parent', 'contentElement']
      });
  
      return provider;
  
      /**
       * Save the configured defaults to be used when the factory is instantiated
       */
      function setDefaults(definition) {
        providerConfig.optionsFactory = definition.options;
        providerConfig.methods = (definition.methods || []).concat(EXPOSED_METHODS);
        return provider;
      }
  
      /**
       * Add a method to the factory that isn't specific to any interim element operations
       */
  
      function addMethod(name, fn) {
        customMethods[name] = fn;
        return provider;
      }
  
      /**
       * Save the configured preset to be used when the factory is instantiated
       */
      function addPreset(name, definition) {
        definition = definition || {};
        definition.methods = definition.methods || [];
        definition.options = definition.options || function() { return {}; };
  
        if (/^cancel|hide|show$/.test(name)) {
          throw new Error("Preset '" + name + "' in " + interimFactoryName + " is reserved!");
        }
        if (definition.methods.indexOf('_options') > -1) {
          throw new Error("Method '_options' in " + interimFactoryName + " is reserved!");
        }
        providerConfig.presets[name] = {
          methods: definition.methods.concat(EXPOSED_METHODS),
          optionsFactory: definition.options,
          argOption: definition.argOption
        };
        return provider;
      }
  
      function addPresetMethod(presetName, methodName, method) {
        providerConfig.presets[presetName][methodName] = method;
      }
  
      /**
       * Create a factory that has the given methods & defaults implementing interimElement
       */
      /* @ngInject */
      function factory($$interimElement, $injector) {
        var defaultMethods;
        var defaultOptions;
        var interimElementService = $$interimElement();
  
        /*
         * publicService is what the developer will be using.
         * It has methods hide(), cancel(), show(), build(), and any other
         * presets which were set during the config phase.
         */
        var publicService = {
          hide: interimElementService.hide,
          cancel: interimElementService.cancel,
          show: showInterimElement,
  
          // Special internal method to destroy an interim element without animations
          // used when navigation changes causes a $scope.$destroy() action
          destroy : destroyInterimElement
        };
  
  
        defaultMethods = providerConfig.methods || [];
        // This must be invoked after the publicService is initialized
        defaultOptions = invokeFactory(providerConfig.optionsFactory, {});
  
        // Copy over the simple custom methods
        angular.forEach(customMethods, function(fn, name) {
          publicService[name] = fn;
        });
  
        angular.forEach(providerConfig.presets, function(definition, name) {
          var presetDefaults = invokeFactory(definition.optionsFactory, {});
          var presetMethods = (definition.methods || []).concat(defaultMethods);
  
          // Every interimElement built with a preset has a field called `$type`,
          // which matches the name of the preset.
          // Eg in preset 'confirm', options.$type === 'confirm'
          angular.extend(presetDefaults, { $type: name });
  
          // This creates a preset class which has setter methods for every
          // method given in the `.addPreset()` function, as well as every
          // method given in the `.setDefaults()` function.
          //
          // @example
          // .setDefaults({
          //   methods: ['hasBackdrop', 'clickOutsideToClose', 'escapeToClose', 'targetEvent'],
          //   options: dialogDefaultOptions
          // })
          // .addPreset('alert', {
          //   methods: ['title', 'ok'],
          //   options: alertDialogOptions
          // })
          //
          // Set values will be passed to the options when interimElement.show() is called.
          function Preset(opts) {
            this._options = angular.extend({}, presetDefaults, opts);
          }
          angular.forEach(presetMethods, function(name) {
            Preset.prototype[name] = function(value) {
              this._options[name] = value;
              return this;
            };
          });
  
          // Create shortcut method for one-linear methods
          if (definition.argOption) {
            var methodName = 'show' + name.charAt(0).toUpperCase() + name.slice(1);
            publicService[methodName] = function(arg) {
              var config = publicService[name](arg);
              return publicService.show(config);
            };
          }
  
          // eg $mdDialog.alert() will return a new alert preset
          publicService[name] = function(arg) {
            // If argOption is supplied, eg `argOption: 'content'`, then we assume
            // if the argument is not an options object then it is the `argOption` option.
            //
            // @example `$mdToast.simple('hello')` // sets options.content to hello
            //                                     // because argOption === 'content'
            if (arguments.length && definition.argOption &&
                !angular.isObject(arg) && !angular.isArray(arg))  {
  
              return (new Preset())[definition.argOption](arg);
  
            } else {
              return new Preset(arg);
            }
  
          };
        });
  
        return publicService;
  
        /**
         *
         */
        function showInterimElement(opts) {
          // opts is either a preset which stores its options on an _options field,
          // or just an object made up of options
          opts = opts || { };
          if (opts._options) opts = opts._options;
  
          return interimElementService.show(
            angular.extend({}, defaultOptions, opts)
          );
        }
  
        /**
         *  Special method to hide and destroy an interimElement WITHOUT
         *  any 'leave` or hide animations ( an immediate force hide/remove )
         *
         *  NOTE: This calls the onRemove() subclass method for each component...
         *  which must have code to respond to `options.$destroy == true`
         */
        function destroyInterimElement(opts) {
            return interimElementService.destroy(opts);
        }
  
        /**
         * Helper to call $injector.invoke with a local of the factory name for
         * this provider.
         * If an $mdDialog is providing options for a dialog and tries to inject
         * $mdDialog, a circular dependency error will happen.
         * We get around that by manually injecting $mdDialog as a local.
         */
        function invokeFactory(factory, defaultVal) {
          var locals = {};
          locals[interimFactoryName] = publicService;
          return $injector.invoke(factory || function() { return defaultVal; }, {}, locals);
        }
  
      }
  
    }
  
    /* @ngInject */
    function InterimElementFactory($document, $q, $rootScope, $timeout, $rootElement, $animate,
                                   $mdUtil, $mdCompiler, $mdTheming, $injector, $exceptionHandler) {
      return function createInterimElementService() {
        var SHOW_CANCELLED = false;
  
        /*
         * @ngdoc service
         * @name $$interimElement.$service
         *
         * @description
         * A service used to control inserting and removing an element into the DOM.
         *
         */
  
        var service;
  
        var showPromises = []; // Promises for the interim's which are currently opening.
        var hidePromises = []; // Promises for the interim's which are currently hiding.
        var showingInterims = []; // Interim elements which are currently showing up.
  
        // Publish instance $$interimElement service;
        // ... used as $mdDialog, $mdToast, $mdMenu, and $mdSelect
  
        return service = {
          show: show,
          hide: waitForInterim(hide),
          cancel: waitForInterim(cancel),
          destroy : destroy,
          $injector_: $injector
        };
  
        /*
         * @ngdoc method
         * @name $$interimElement.$service#show
         * @kind function
         *
         * @description
         * Adds the `$interimElement` to the DOM and returns a special promise that will be resolved or rejected
         * with hide or cancel, respectively. To external cancel/hide, developers should use the
         *
         * @param {*} options is hashMap of settings
         * @returns a Promise
         *
         */
        function show(options) {
          options = options || {};
          var interimElement = new InterimElement(options || {});
  
          // When an interim element is currently showing, we have to cancel it.
          // Just hiding it, will resolve the InterimElement's promise, the promise should be
          // rejected instead.
          var hideAction = options.multiple ? $q.resolve() : $q.all(showPromises);
  
          if (!options.multiple) {
            // Wait for all opening interim's to finish their transition.
            hideAction = hideAction.then(function() {
              // Wait for all closing and showing interim's to be completely closed.
              var promiseArray = hidePromises.concat(showingInterims.map(service.cancel));
              return $q.all(promiseArray);
            });
          }
  
          var showAction = hideAction.then(function() {
  
            return interimElement
              .show()
              .catch(function(reason) { return reason; })
              .finally(function() {
                showPromises.splice(showPromises.indexOf(showAction), 1);
                showingInterims.push(interimElement);
              });
  
          });
  
          showPromises.push(showAction);
  
          // In AngularJS 1.6+, exceptions inside promises will cause a rejection. We need to handle
          // the rejection and only log it if it's an error.
          interimElement.deferred.promise.catch(function(fault) {
            if (fault instanceof Error) {
              $exceptionHandler(fault);
            }
  
            return fault;
          });
  
          // Return a promise that will be resolved when the interim
          // element is hidden or cancelled...
          return interimElement.deferred.promise;
        }
  
        /*
         * @ngdoc method
         * @name $$interimElement.$service#hide
         * @kind function
         *
         * @description
         * Removes the `$interimElement` from the DOM and resolves the promise returned from `show`
         *
         * @param {*} resolveParam Data to resolve the promise with
         * @returns a Promise that will be resolved after the element has been removed.
         *
         */
        function hide(reason, options) {
          options = options || {};
  
          if (options.closeAll) {
            // We have to make a shallow copy of the array, because otherwise the map will break.
            return $q.all(showingInterims.slice().reverse().map(closeElement));
          } else if (options.closeTo !== undefined) {
            return $q.all(showingInterims.slice(options.closeTo).map(closeElement));
          }
  
          // Hide the latest showing interim element.
          return closeElement(showingInterims[showingInterims.length - 1]);
  
          function closeElement(interim) {
  
            var hideAction = interim
              .remove(reason, false, options || { })
              .catch(function(reason) { return reason; })
              .finally(function() {
                hidePromises.splice(hidePromises.indexOf(hideAction), 1);
              });
  
            showingInterims.splice(showingInterims.indexOf(interim), 1);
            hidePromises.push(hideAction);
  
            return interim.deferred.promise;
          }
        }
  
        /*
         * @ngdoc method
         * @name $$interimElement.$service#cancel
         * @kind function
         *
         * @description
         * Removes the `$interimElement` from the DOM and rejects the promise returned from `show`
         *
         * @param {*} reason Data to reject the promise with
         * @returns Promise that will be resolved after the element has been removed.
         *
         */
        function cancel(reason, options) {
          var interim = showingInterims.pop();
          if (!interim) {
            return $q.when(reason);
          }
  
          var cancelAction = interim
            .remove(reason, true, options || {})
            .catch(function(reason) { return reason; })
            .finally(function() {
              hidePromises.splice(hidePromises.indexOf(cancelAction), 1);
            });
  
          hidePromises.push(cancelAction);
  
          // Since AngularJS 1.6.7, promises will be logged to $exceptionHandler when the promise
          // is not handling the rejection. We create a pseudo catch handler, which will prevent the
          // promise from being logged to the $exceptionHandler.
          return interim.deferred.promise.catch(angular.noop);
        }
  
        /**
         * Creates a function to wait for at least one interim element to be available.
         * @param callbackFn Function to be used as callback
         * @returns {Function}
         */
        function waitForInterim(callbackFn) {
          return function() {
            var fnArguments = arguments;
  
            if (!showingInterims.length) {
              // When there are still interim's opening, then wait for the first interim element to
              // finish its open animation.
              if (showPromises.length) {
                return showPromises[0].finally(function () {
                  return callbackFn.apply(service, fnArguments);
                });
              }
  
              return $q.when("No interim elements currently showing up.");
            }
  
            return callbackFn.apply(service, fnArguments);
          };
        }
  
        /*
         * Special method to quick-remove the interim element without animations
         * Note: interim elements are in "interim containers"
         */
        function destroy(targetEl) {
          var interim = !targetEl ? showingInterims.shift() : null;
  
          var parentEl = angular.element(targetEl).length && angular.element(targetEl)[0].parentNode;
  
          if (parentEl) {
            // Try to find the interim in the stack which corresponds to the supplied DOM element.
            var filtered = showingInterims.filter(function(entry) {
              return entry.options.element[0] === parentEl;
            });
  
            // Note: This function might be called when the element already has been removed,
            // in which case we won't find any matches.
            if (filtered.length) {
              interim = filtered[0];
              showingInterims.splice(showingInterims.indexOf(interim), 1);
            }
          }
  
          return interim ? interim.remove(SHOW_CANCELLED, false, { '$destroy': true }) :
                           $q.when(SHOW_CANCELLED);
        }
  
        /*
         * Internal Interim Element Object
         * Used internally to manage the DOM element and related data
         */
        function InterimElement(options) {
          var self, element, showAction = $q.when(true);
  
          options = configureScopeAndTransitions(options);
  
          return self = {
            options : options,
            deferred: $q.defer(),
            show    : createAndTransitionIn,
            remove  : transitionOutAndRemove
          };
  
          /**
           * Compile, link, and show this interim element
           * Use optional autoHided and transition-in effects
           */
          function createAndTransitionIn() {
            return $q(function(resolve, reject) {
  
              // Trigger onCompiling callback before the compilation starts.
              // This is useful, when modifying options, which can be influenced by developers.
              options.onCompiling && options.onCompiling(options);
  
              compileElement(options)
                .then(function( compiledData ) {
                  element = linkElement( compiledData, options );
  
                  // Expose the cleanup function from the compiler.
                  options.cleanupElement = compiledData.cleanup;
  
                  showAction = showElement(element, options, compiledData.controller)
                    .then(resolve, rejectAll);
                }).catch(rejectAll);
  
              function rejectAll(fault) {
                // Force the '$md<xxx>.show()' promise to reject
                self.deferred.reject(fault);
  
                // Continue rejection propagation
                reject(fault);
              }
            });
          }
  
          /**
           * After the show process has finished/rejected:
           * - announce 'removing',
           * - perform the transition-out, and
           * - perform optional clean up scope.
           */
          function transitionOutAndRemove(response, isCancelled, opts) {
  
            // abort if the show() and compile failed
            if ( !element ) return $q.when(false);
  
            options = angular.extend(options || {}, opts || {});
            options.cancelAutoHide && options.cancelAutoHide();
            options.element.triggerHandler('$mdInterimElementRemove');
  
            if ( options.$destroy === true ) {
  
              return hideElement(options.element, options).then(function(){
                (isCancelled && rejectAll(response)) || resolveAll(response);
              });
  
            } else {
              $q.when(showAction).finally(function() {
                hideElement(options.element, options).then(function() {
                  isCancelled ? rejectAll(response) : resolveAll(response);
                }, rejectAll);
              });
  
              return self.deferred.promise;
            }
  
  
            /**
             * The `show()` returns a promise that will be resolved when the interim
             * element is hidden or cancelled...
             */
            function resolveAll(response) {
              self.deferred.resolve(response);
            }
  
            /**
             * Force the '$md<xxx>.show()' promise to reject
             */
            function rejectAll(fault) {
              self.deferred.reject(fault);
            }
          }
  
          /**
           * Prepare optional isolated scope and prepare $animate with default enter and leave
           * transitions for the new element instance.
           */
          function configureScopeAndTransitions(options) {
            options = options || { };
            if ( options.template ) {
              options.template = $mdUtil.processTemplate(options.template);
            }
  
            return angular.extend({
              preserveScope: false,
              cancelAutoHide : angular.noop,
              scope: options.scope || $rootScope.$new(options.isolateScope),
  
              /**
               * Default usage to enable $animate to transition-in; can be easily overridden via 'options'
               */
              onShow: function transitionIn(scope, element, options) {
                return $animate.enter(element, options.parent);
              },
  
              /**
               * Default usage to enable $animate to transition-out; can be easily overridden via 'options'
               */
              onRemove: function transitionOut(scope, element) {
                // Element could be undefined if a new element is shown before
                // the old one finishes compiling.
                return element && $animate.leave(element) || $q.when();
              }
            }, options );
  
          }
  
          /**
           * Compile an element with a templateUrl, controller, and locals
           */
          function compileElement(options) {
  
            var compiled = !options.skipCompile ? $mdCompiler.compile(options) : null;
  
            return compiled || $q(function (resolve) {
                resolve({
                  locals: {},
                  link: function () {
                    return options.element;
                  }
                });
              });
          }
  
          /**
           *  Link an element with compiled configuration
           */
          function linkElement(compileData, options){
            angular.extend(compileData.locals, options);
  
            var element = compileData.link(options.scope);
  
            // Search for parent at insertion time, if not specified
            options.element = element;
            options.parent = findParent(element, options);
            if (options.themable) $mdTheming(element);
  
            return element;
          }
  
          /**
           * Search for parent at insertion time, if not specified
           */
          function findParent(element, options) {
            var parent = options.parent;
  
            // Search for parent at insertion time, if not specified
            if (angular.isFunction(parent)) {
              parent = parent(options.scope, element, options);
            } else if (angular.isString(parent)) {
              parent = angular.element($document[0].querySelector(parent));
            } else {
              parent = angular.element(parent);
            }
  
            // If parent querySelector/getter function fails, or it's just null,
            // find a default.
            if (!(parent || {}).length) {
              var el;
              if ($rootElement[0] && $rootElement[0].querySelector) {
                el = $rootElement[0].querySelector(':not(svg) > body');
              }
              if (!el) el = $rootElement[0];
              if (el.nodeName == '#comment') {
                el = $document[0].body;
              }
              return angular.element(el);
            }
  
            return parent;
          }
  
          /**
           * If auto-hide is enabled, start timer and prepare cancel function
           */
          function startAutoHide() {
            var autoHideTimer, cancelAutoHide = angular.noop;
  
            if (options.hideDelay) {
              autoHideTimer = $timeout(service.hide, options.hideDelay) ;
              cancelAutoHide = function() {
                $timeout.cancel(autoHideTimer);
              };
            }
  
            // Cache for subsequent use
            options.cancelAutoHide = function() {
              cancelAutoHide();
              options.cancelAutoHide = undefined;
            };
          }
  
          /**
           * Show the element ( with transitions), notify complete and start
           * optional auto-Hide
           */
          function showElement(element, options, controller) {
            // Trigger onShowing callback before the `show()` starts
            var notifyShowing = options.onShowing || angular.noop;
            // Trigger onComplete callback when the `show()` finishes
            var notifyComplete = options.onComplete || angular.noop;
  
            // Necessary for consistency between AngularJS 1.5 and 1.6.
            try {
              notifyShowing(options.scope, element, options, controller);
            } catch (e) {
              return $q.reject(e);
            }
  
            return $q(function (resolve, reject) {
              try {
                // Start transitionIn
                $q.when(options.onShow(options.scope, element, options, controller))
                  .then(function () {
                    notifyComplete(options.scope, element, options);
                    startAutoHide();
  
                    resolve(element);
                  }, reject);
  
              } catch (e) {
                reject(e.message);
              }
            });
          }
  
          function hideElement(element, options) {
            var announceRemoving = options.onRemoving || angular.noop;
  
            return $q(function (resolve, reject) {
              try {
                // Start transitionIn
                var action = $q.when( options.onRemove(options.scope, element, options) || true );
  
                // Trigger callback *before* the remove operation starts
                announceRemoving(element, action);
  
                if (options.$destroy) {
                  // For $destroy, onRemove should be synchronous
                  resolve(element);
  
                  if (!options.preserveScope && options.scope ) {
                    // scope destroy should still be be done after the current digest is done
                    action.then( function() { options.scope.$destroy(); });
                  }
                } else {
                  // Wait until transition-out is done
                  action.then(function () {
                    if (!options.preserveScope && options.scope ) {
                      options.scope.$destroy();
                    }
  
                    resolve(element);
                  }, reject);
                }
              } catch (e) {
                reject(e.message);
              }
            });
          }
  
        }
      };
  
    }
  
  }
func_documentation_string: /*
  @ngdoc service
  @name $$interimElement
  @module material.core
  
  @description
  
  Factory that constructs `$$interimElement.$service` services.
  Used internally in material design for elements that appear on screen temporarily.
  The service provides a promise-like API for interacting with the temporary
  elements.
  
  ```js
  app.service('$mdToast', function($$interimElement) {
  var $mdToast = $$interimElement(toastDefaultOptions);
  return $mdToast;
  });
  ```
  @param {object=} defaultOptions Options used by default for the `show` method on the service.
  
  @returns {$$interimElement.$service}