text:
/*
    Name: Henderson
    Description: Responsive VCard Template
    Version: 2.0
    Author: MountainTheme

    TABLE OF CONTENTS
    ---------------------------
     1. Loading
     2. owlCarousel
     3. NiceScroll
     4. Swiper Slider
     5. Isotope
     6. Nivo - Lightbox
     7. Video Background
     8. Contact form
     9. Google Map
*/

(function($){
   'use strict';

    $(window).load(function() {

/* ================================= */
/* :::::::::: 1. Loading ::::::::::: */
/* ================================= */

    if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
         $('#video').css({"display" : "none"});
      }

    $(".loader-icon").delay(500).fadeOut();
    $("#page-loader").delay(700).fadeOut("slow");

    $(".icon-mobile").on("click", function() {
    $(this).toggleClass("s-active");
    $(".navigation").toggleClass("menu-mobile animated fadeIn");
    });

/* ================================= */
/* ::::::::: 2. OwlCarousel :::::::: */
/* ================================= */

$("#owl-blog").owlCarousel({

    // Most important owl features
    items : 1,
    itemsCustom : false,
    itemsDesktop : [1199,3],
    itemsDesktopSmall : [980,3],
    itemsTabletSmall: false,
    itemsMobile : [479,1],
    singleItem : false,
    itemsScaleUp : false,

    //Basic Speeds
    slideSpeed : 200,
    paginationSpeed : 800,
    rewindSpeed : 1000,

    //Autoplay
    autoPlay : true,
    stopOnHover : false,

    //Pagination
    pagination : false,
    paginationNumbers: false,

    // Responsive
    responsive: true,
    responsiveRefreshRate : 200,
    responsiveBaseWidth: window,

});

/* ================================= */
/* ::::::::: 3. NiceScroll ::::::::: */
/* ================================= */

$(".content").niceScroll({
  cursorcolor:"#3d4a6e",
  cursorwidth: "6px",
  cursorborderradius:"5px",
  cursorborder: "0px",
  zindex: 999999,
  railpadding: { top: 0, right: 1, left: 0, bottom: 0 },
});

/* ================================= */
/* :::::::: 4. Swiper Slider ::::::: */
/* ================================= */

  var galleryTop = new Swiper('.slider-left', {
        speed: 900,
        loop: true,
        effect: 'fade',
        centeredSlides: true,
        autoplay: 2500,
        simulateTouch: false,
    });

/* ================================= */
/* ::::::::: 5. Isotope :::::::::::: */
/* ================================= */

  // init Isotope
  var $container = $('.grid').isotope({
    itemSelector: '.element-item',
    masonry: {
      columnWidth: 200,
    }
});

  // filter functions
  var filterFns = {
    // show if number is greater than 50
    numberGreaterThan50: function() {
      var number = $(this).find('.number').text();
      return parseInt( number, 10 ) > 50;
    },
    // show if name ends with -ium
    ium: function() {
      var name = $(this).find('.name').text();
      return name.match( /ium$/ );
    }
  };

  // bind filter button click
  $('#filters').on( 'click', 'button', function() {
    var filterValue = $( this ).attr('data-filter');
    // use filterFn if matches value
    filterValue = filterFns[ filterValue ] || filterValue;
    $container.isotope({ filter: filterValue });
  });

  // change is-checked class on buttons
  $('.button-group').each( function( i, buttonGroup ) {
    var $buttonGroup = $( buttonGroup );
    $buttonGroup.on( 'click', 'button', function() {
      $buttonGroup.find('.is-checked').removeClass('is-checked');
      $( this ).addClass('is-checked');
    });

/* ================================= */
/* ::::: 6. Nivo - Lightbox :::::::: */
/* ================================= */

$('.nivo-lbox').nivoLightbox({effect:'fade'});

/* ================================= */
/* :::::: 7. Video Background :::::: */
/* ================================= */

var video = $('#video').data('video');
var mute = $('#video').data('mute');

$('#video').YTPlayer({
  videoId: video,
  mute: mute,
  fitToBackground: true,
});

/* ================================= */
/* :::::::: 8. Contact form :::::::: */
/* ================================= */

      $('#submit').on("click", function() {
           // validate and process form here
           $("#ajax-contact-form").validate({

                  rules:{

                        name:{
                            required: true,
                        },

                        email:{
                            required: true,
                            email: true,
                        },

                        msg:{
                            required: true,
                        },
                   },

                   messages:{

                          name:{
                            required: "",
                        },

                        email:{
                            required: "",
                            email: "",
                        },

                          msg:{
                            required: "",
                        },

                   },

                // JQuery's awesome submit handler.
                submitHandler: function(form) {

                     // Create variables from the form
                     var name = $('input#name').val();
                     var email = $('input#email').val();
                     var msg = $('textarea#msg').val();

                     // Create variables that will be sent in a URL string to contact.php
                     var dataString = '&name='+ name + '&email=' + email + '&msg=' + msg;

                        $.ajax({
                            type: "POST",
                            url: "php/contact.php",
                            data: dataString,
                            success: function(data) {
                                  if(data == 'OK') {
                                    var result = '
 Your email was sent. Thanks!
';
                                    $("#ajax-contact-form").find('input[type=text], input[type=email], textarea').val("");

                                  } else {
                                  result = data;
                                 }
                          $('#note').html(result);

                          }

                      });
                     return false;
               }
          });
    });

/* ================================= */
/* :::::::: 9. Google Map :::::::::: */
/* ================================= */

  //set your google maps parameters
  var latitude = -37.8602828,
    longitude = 145.079616,
    map_zoom = 9;

  //google map custom marker icon - .png fallback for IE11
  var is_internetExplorer11= navigator.userAgent.toLowerCase().indexOf('trident') > -1;
  var marker_url = ( is_internetExplorer11 ) ? 'images/icon-location.png' : 'images/icon-location.png';

  //define the basic color of your map, plus a value for saturation and brightness
  var main_color = '#2d313f',
    saturation_value= -20,
    brightness_value= 5;

  //we define here the style of the map
  var style= [
    {
      //set saturation for the labels on the map
      elementType: "labels",
      stylers: [
        {saturation: saturation_value},
      ]
    },
      { //poi stands for point of interest - don't show these lables on the map
      featureType: "poi",
      elementType: "labels",
      stylers: [
        {visibility: "off"},
      ]
    },
    {
      //don't show highways lables on the map
          featureType: 'road.highway',
          elementType: 'labels',
          stylers: [
              {visibility: "off"},
          ]
      },
    {
      //don't show local road lables on the map
      featureType: "road.local",
      elementType: "labels.icon",
      stylers: [
        {visibility: "off"},
      ]
    },
    {
      //don't show arterial road lables on the map
      featureType: "road.arterial",
      elementType: "labels.icon",
      stylers: [
        {visibility: "off"},
      ]
    },
    {
      //don't show road lables on the map
      featureType: "road",
      elementType: "geometry.stroke",
      stylers: [
        {visibility: "off"},
      ]
    },
    //style different elements on the map
    {
      featureType: "transit",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "poi",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "poi.government",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "poi.sport_complex",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "poi.attraction",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "poi.business",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "transit",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "transit.station",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "landscape",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]

    },
    {
      featureType: "road",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "road.highway",
      elementType: "geometry.fill",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    },
    {
      featureType: "water",
      elementType: "geometry",
      stylers: [
        { hue: main_color },
        { visibility: "on" },
        { lightness: brightness_value },
        { saturation: saturation_value },
      ]
    }
  ];

  //set google map options
  var map_options = {
        center: new google.maps.LatLng(latitude, longitude),
        zoom: map_zoom,
        panControl: false,
        zoomControl: false,
        mapTypeControl: false,
        streetViewControl: false,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scrollwheel: false,
        styles: style,
    }
    //inizialize the map
  var map = new google.maps.Map(document.getElementById('google-container'), map_options);
  //add a custom marker to the map

 var contentString = '
'+
      '
CONTACT INFORMATION.
'+
         '
'+
       '
Melbourne, Australia
'+
       '
765-302-2878
'+
       '
name@domain.com
'+
       '
mycompanyname.com
'+
       '
'+
      '
';

  var infowindow = new google.maps.InfoWindow({
      content: contentString,
      maxWidth: 300,

  });

   var marker = new google.maps.Marker({
      position: new google.maps.LatLng(latitude, longitude),
      map: map,
      title: 'Melbourne, Australia',
      visible: true,
      icon: marker_url,
  });

    infowindow.open(map,marker);

 google.maps.event.addListener(marker, 'click', function() {
    infowindow.open(map,marker);
  });

  google.maps.event.addDomListener(window, "resize", function() {
     var center = map.getCenter();
     google.maps.event.trigger(map, "resize");
     map.setCenter(center);

    });

  //add custom buttons for the zoom-in/zoom-out on the map
  function CustomZoomControl(controlDiv, map) {
    //grap the zoom elements from the DOM and insert them in the map
      var controlUIzoomIn= document.getElementById('zoom-in'),
        controlUIzoomOut= document.getElementById('zoom-out');
      controlDiv.appendChild(controlUIzoomIn);
      controlDiv.appendChild(controlUIzoomOut);

    // Setup the click event listeners and zoom-in or out according to the clicked element
    google.maps.event.addDomListener(controlUIzoomIn, 'click', function() {
        map.setZoom(map.getZoom()+1)
    });
    google.maps.event.addDomListener(controlUIzoomOut, 'click', function() {
        map.setZoom(map.getZoom()-1)
    });
  }

  var zoomControlDiv = document.createElement('div');
  var zoomControl = new CustomZoomControl(zoomControlDiv, map);

    //insert the zoom div on the top left of the map
    map.controls[google.maps.ControlPosition.LEFT_TOP].push(zoomControlDiv);

});
});
})(jQuery);


text:
copyright:
  years: 2015, 2017
lastupdated: "2017-03-14"

---

{:new_window: target="blank"}
{:shortdesc: .shortdesc}
{:screen: .screen}
{:codeblock: .codeblock}
{:pre: .pre}

# Ampliando o gerenciamento de dispositivo
{: #custom_actions}

É possível estender os recursos de gerenciamento de dispositivo no {{site.data.keyword.iot_full}} para atender seus requisitos incluindo extensões de gerenciamento de dispositivo. As extensões de gerenciamento de dispositivo podem ser incluídas usando a API de REST ou o painel {{site.data.keyword.iot_short_notm}}.

Por padrão, as ações de gerenciamento de dispositivo a seguir são suportadas pelo {{site.data.keyword.iot_short_notm}}:
- Reinicialização do dispositivo
- Reconfiguração de fábrica
- Download de firmware
- Atualização de Firmware

## Pacotes de extensão de gerenciamento de dispositivo
{: #device_management_ext}

Um pacote de extensão de gerenciamento de dispositivo é um documento JSON que define pelo menos uma ação de gerenciamento de dispositivo. As ações podem ser iniciadas em quaisquer dispositivos que suportem as ações usando o painel {{site.data.keyword.iot_short_notm}} ou a API de REST.

A amostra de código a seguir mostra o formato típico de um pacote de extensão de gerenciamento de dispositivo:

```

	{
		"bundleId": "<unique identifier>",
		"displayName": {
			"<locale 0>": "<localized display name 0>"
		},
		"description": {
			"<locale 0>": "<localized description 0>"
		},
		"version": "<bundle version>",
		"provider": "<bundle provider>",
		"actions": {
			"<actionId 0>": {
				"actionDisplayName": {
					"<locale 0>": "<localized action display name 0>"
				},
				"description": {
					"<locale 0>": "<localized description>"
				},
				"parameters": [
					{
						"name": "<parameterId>",
						"value": "<regex pattern for value checking>",
						"required": false,
						"defaultValue": "<default>"
					}
				]
			}
		}
	}

```

### Incluindo um pacote de gerenciamento de dispositivo customizado

Os pacotes de gerenciamento de dispositivo customizado podem ser incluídos usando o painel do {{site.data.keyword.iot_short_notm}} ou usando a API.

Para incluir um pacote de gerenciamento de dispositivo customizado usando o painel do {{site.data.keyword.iot_short_notm}}:

1. No painel do {{site.data.keyword.iot_short_notm}}, clique em **Configurações** na barra de navegação.
2. Clique em **Pacotes de gerenciamento de dispositivo customizado**.
3. Clique no botão **Incluir pacote**.
4. Selecione seu arquivo de pacote e clique em **Abrir**.

Para incluir um pacote de gerenciamento de dispositivo customizado usando a API, veja a [documentação da API do {{site.data.keyword.iot_short_notm}} ![Ícone de link externo](../../../../icons/launch-glyph.svg "Ícone de link externo")](https://docs.internetofthings.ibmcloud.com/swagger/v0002.html){: new_window}.

### Propriedades do pacote de extensão

Um pacote de extensão de gerenciamento de dispositivo contém as propriedades a seguir:

|Propriedade|Descrição|Necessárias
|:---|:---|:---|
|`bundleId`|Identificador exclusivo para uma extensão de gerenciamento de dispositivo.|Sim|
|`version`|Sequência de versões para uma extensão de gerenciamento de dispositivo.|no|
|`provider`|Sequência do provedor para uma extensão de gerenciamento de dispositivo, limitada a 1024 caracteres.|no|
|`displayName`|Mapa de pares de chave-valor `locale`: `String` mostrados no painel do {{site.data.keyword.iot_short_notm}}. Deve-se especificar pelo menos uma entrada.|Sim|
|`description`|Mapa de pares de chave-valor `locale`: `String` usados para exibição no painel do {{site.data.keyword.iot_short_notm}}. Se definido, deve-se especificar pelo menos uma entrada.|no|
|`actions`| Mapa de pares chave-valor `actionId`: `<action>` que definem as ações que estão contidas em uma extensão de gerenciamento de dispositivo. Deve-se especificar pelo menos uma entrada.|Sim|

### Propriedades para cada ação:

|Propriedade|Descrição|Necessárias
|:---|:---|
|`actionDisplayName`|Mapa de pares de chave-valor `locale`: `String` mostrados no painel do {{site.data.keyword.iot_short_notm}}. Deve-se especificar pelo menos uma entrada.|Sim|
|`description`|Mapa de pares de chave-valor `locale`: `String` usados para exibição no painel do {{site.data.keyword.iot_short_notm}}. Opcional. Deve-se especificar pelo menos uma entrada.|no|
|`parameters`|Matriz de parâmetros que são permitidos para uma ação específica. Se definido, deve-se especificar pelo menos uma entrada.|no|

### Propriedades para cada parâmetro de ação:

|Propriedade|Descrição|Necessárias
|:---|:---|
|`name`|Identificador exclusivo para um parâmetro em uma ação|Sim|
|`value`|Expressão regular usada para validar valores de parâmetros quando uma solicitação é iniciada. Se não for especificada, a validação não ocorre.|no|
|`required`|O valor booleano que determina se o parâmetro é necessário. O valor está configurado por padrão como false. |no|
|`defaultValue`|Valor a ser usado se o parâmetro não for fornecido quando uma solicitação for iniciada|no|

**Nota:** os valores de `bundleId`, `version`, `actionId` e `parameterId` são limitados a 255 caracteres e podem consistir somente em caracteres alfanuméricos (a-z, A-Z, 0-9) e os caracteres especiais a seguir:
 - travessão (-)
 - sublinhado (\_)
 - ponto (.)

## APIs REST
{: #rest_api}

Use os comandos da API (interface de programação de aplicativos) REST do {{site.data.keyword.iot_short_notm}} para gerenciar seus pacotes de extensão:

- Para obter uma lista de todos os pacotes de extensão de gerenciamento de dispositivo:
  `GET https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/custom/bundle`
- Para criar um novo pacote de extensão de gerenciamento de dispositivo:
  `POST https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/custom/bundle`
- Para obter um pacote de extensão de gerenciamento de dispositivo:
  `GET https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/custom/bundle/{bundleId}`
- Para atualizar um pacote de extensão de gerenciamento de dispositivo:
  `PUT https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/custom/bundle/{bundleId}`
- Para excluir um pacote de extensão de gerenciamento de dispositivo:
  `DELETE https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/custom/bundle/{bundleId}`

Para obter mais informações sobre as APIs de REST para os pacotes de extensão de gerenciamento de dispositivo, veja a documentação do [{{site.data.keyword.iot_short_notm}} API V2 ![Ícone de link externo](../../../../icons/launch-glyph.svg "Ícone de link externo")](https://docs.internetofthings.ibmcloud.com/swagger/v0002.html){: new_window}.

## Suportando ações de gerenciamento de dispositivo customizadas
{: #supporting_custom_device_management_actions}

As ações de gerenciamento de dispositivo definidas em seus pacotes de extensão podem ser iniciadas somente por dispositivos que suportam essas ações. Quando um dispositivo publica uma solicitação de gerenciamento no {{site.data.keyword.iot_short_notm}}, o dispositivo especifica os tipos de ações que ele pode suportar.

Para especificar ações customizadas de um pacote de extensão, o dispositivo deve especificar o identificador de pacote configurável para o pacote de extensão no objeto de suporte da solicitação, conforme mostrado no exemplo a seguir:

```
	Outgoing message from device:

	Topic: iotdevice-1/mgmt/manage
	{
		"d": {
			"supports": {
				"deviceActions": false,
				"firmwareActions": false,
				"<bundleId>": true
			}
		},
		"reqId": "<request id>"
	}

	Incoming response from server:

	Topic: iotdm-1/response
	{
		"rc": 200,
		"reqId": "<request id>"
	}

```

Para obter mais informações sobre solicitações de gerenciamento de dispositivo, consulte [Protocolo de gerenciamento de dispositivo](index.html).

## Iniciando ações de gerenciamento de dispositivo customizadas
{: #initiating_custom_dm_actions}

Para iniciar ações customizadas de gerenciamento de dispositivo, use o comando da API (interface de programação de aplicativos) REST a seguir, que é o comando padrão para iniciar ações de gerenciamento de dispositivo:

`POST https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/requests`

Deve-se fornecer as informações a seguir ao iniciar uma solicitação:

- A ação `<bundleId>/<actionId>`
- Uma lista de dispositivos nos quais iniciar a ação, até no máximo 5000 dispositivos
- Uma lista de parâmetros que estão definidos na definição da ação customizada

A carga útil para iniciar uma solicitação tem o formato a seguir:

```
	{
		"action": "<bundleId>/<actionId>",
		"devices": [
			{
				"typeId": "<deviceType 0>",
				"deviceId": "<deviceId 0>"
			}
		],
		"parameters": [
			{
				"name": "<parameter0>",
				"value": "<parameter0 value>"
			}
		]
	}

```

## Manipulando ações de gerenciamento de dispositivo customizadas
{: #handling_custom_dm_actions}

Quando uma ação customizada é iniciada em um dispositivo, uma mensagem MQTT é publicada no dispositivo. A mensagem MQTT contém quaisquer parâmetros que foram especificados como parte da solicitação. Quando o dispositivo recebe a mensagem MQTT, ele executa a ação ou responde com um código de erro que indica por que ele não pode concluir a ação no momento.

Quando uma ação de dispositivo é concluída com sucesso, o dispositivo publica uma resposta na qual o valor de `rc` está configurado para `200`.

A extração a seguir fornece um exemplo da troca que ocorre entre um servidor e um dispositivo.

```
	Incoming message from the server:

	Topic: iotdm-1/mgmt/custom/<bundleId>/<actionId>
	{
		"d": {
			"fields": [
				{
					"field": "<parameter0>",
					"value": "<parameter0 value>"
				}
			]
		},
		"reqId": "<request id>"
	}

	... device carries out the requested action ...

	Outgoing message from the device:

	Topic: iotdevice-1/response
	{
		"rc": 200,
		"reqId": "<request id>"
	}

```

## Exemplo
{: #example}

O exemplo a seguir demonstra como é possível definir uma nova extensão de gerenciamento de dispositivo e executar uma ação que está definida nessa extensão.

Algumas empresas fabricam dispositivos `exampleDeviceType`. É possível instalar e gerenciar plug-ins para execução em dispositivos `exampleDeviceType`. Para facilitar o gerenciamento remoto de plug-ins em dispositivos `exampleDeviceType`, o fabricante geralmente fornece uma extensão de gerenciamento de dispositivo que é possível importar para sua organização do {{site.data.keyword.iot_short_notm}}.

O documento JSON de extensão a seguir é usado neste exemplo:

```
	{
		"bundleId": "exampleDeviceType-actions-v1",
		"displayName": {
			"en_US": "exampleDeviceType Actions v1"
		},
		"description": {
			"en_US": "Device management actions for exampleDeviceType devices"
		},
		"version": "1.0",
		"provider": "some company",
		"actions": {
			"installPlugin": {
				"actionDisplayName": {
					"en_US": "Install Plug-in"
				},
				"description": {
					"en_US": "Install a new plug-in on the device"
				},
				"parameters": [
					{
						"name": "pluginId",
						"value": "\\w+",
						"required": true
					},
					{
						"name": "pluginURI",
						"value": "((http:\\/\\/|https:\\/\\/)(.*)+)",
						"required": true
					}
				]
			},
			"enablePlugin": {
				"actionDisplayName": {
					"en_US": "Enable Plug-in"
				},
				"description": {
					"en_US": "Enables a plug-in on the device"
				},
				"parameters": [
					{
						"name": "pluginId",
						"value": "\\w+",
						"required": true
					}
				]
			},
			"disablePlugin": {
				"actionDisplayName": {
					"en_US": "Disable Plug-in"
				},
				"description": {
					"en_US": "Disables a plug-in on the device"
				},
				"parameters": [
					{
						"name": "pluginId",
						"value": "\\w+",
						"required": true
					}
				]
			},
			"uninstallPlugin": {
				"actionDisplayName": {
					"en_US": "Uninstall Plug-in"
				},
				"description": {
					"en_US": "Uninstall a plug-in from the device"
				},
				"parameters": [
					{
						"name": "pluginId",
						"value": "\\w+",
						"required": true
					}
				]
			}
		}
	}

```
Nesse pacote de extensão de gerenciamento de dispositivo, estão definidas as ações a seguir:

- **installPlugin**
- **enablePlugin**
- **disablePlugin**
- **uninstallPlugin**

Para incluir a extensão, use o comando da API (interface de programação de aplicativos) REST a seguir:

`POST https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/custom/bundle`

Os dispositivos registrados na organização `<orgID>` podem especificar que eles suportam ações `exampleDeviceType-actions-v1` ao publicarem uma solicitação de gerenciamento, o que é mostrado no exemplo a seguir:

```
	Outgoing message from device:

	Topic: iotdevice-1/mgmt/manage
	{
		"d": {
			"supports": {
				"exampleDeviceType-actions-v1": true
			}
		},
		"reqId": "f38faafc-53de-47a8-a940-e697552c3194"
	}

```
O dispositivo recebe a resposta a seguir do {{site.data.keyword.iot_short_notm}}:

```
	Incoming message from server:

	Topic: iotdm-1/response
	{
		"rc": 200,
		"reqId": "f38faafc-53de-47a8-a940-e697552c3194"
	}

```
Neste ponto, é possível iniciar as ações do dispositivo definidas na extensão `exampleIoT-exampleDeviceType-v1`.

A carga útil a seguir é usada para iniciar uma ação `installPlugin`:

```
	{
		"action": "exampleDeviceType-actions-v1/installPlugin",
		"devices": [
			{
				"typeId": "exampleDeviceType",
				"deviceId": "device0"
			},
			{
				"typeId": "exampleDeviceType",
				"deviceId": "device1"
			}
		],
		"parameters": [
			{
				"name": "pluginId",
				"value": "testPluginA"
			},
			{
				"name": "pluginURI",
				"value": "http://www.example.com/testPluginA.zip"
			}
		]
	}

```
Inicie a solicitação usando o comando da API (interface de programação de aplicativos) REST a seguir:

`POST https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/requests`

Quando o comando for enviado, os dispositivos `device0` e `device1` do tipo `exampleDeviceType` recebem a mensagem MQTT a seguir:

```
	Incoming message from server:

	Topic: iotdm-1/mgmt/custom/exampleDeviceType-actions-v1/installPlugin
	{
		"d": {
			"fields": [
				{
					"field": "pluginId",
					"value": "testPluginA"
				},
				{
					"field": "pluginURI",
					"value": "http://www.exampleiot.com/testPluginA.zip"
				}
			]
		},
		"reqId": "d38faafc-53de-47a8-a940-e697552c3194"
	}

```

Cada dispositivo toma uma ação na mensagem e instala o plug-in especificado. Quando a instalação for concluída, os dispositivos enviam uma mensagem para indicar que a ação foi concluída com sucesso.

```
	Outgoing message from device:

	Topic: iotdevice-1/response
	{
		"rc": 200,
		"reqId": "d38faafc-53de-47a8-a940-e697552c3194"
	}

```

Neste momento, a ação de gerenciamento de dispositivo `installPlugin` é concluída.

## Exemplos de API
{: #api_examples}

Use as solicitações da API (interface de programação de aplicativos) a seguir para gerenciar seus dispositivos:

- Para criar uma nova extensão de gerenciamento de dispositivo:

`curl -XPOST -d '<insert payload here>' -H "Content-Type: application/json" -u "<apiKey>:<apiToken>" https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/custom/bundle`

- Para listar as extensões de gerenciamento de dispositivo:

`curl -XGET -H "Content-Type: application/json" -u "<apiKey>:<apiToken>" https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/custom/bundle`

- Para iniciar uma solicitação de gerenciamento de dispositivo:

`curl -XPOST -d '<insert payload here>' -H "Content-Type: application/json" -u "<apiKey>:<apiToken>" https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/requests`

- Para listar solicitações de gerenciamento de dispositivo que estão em andamento ou concluídas:

`curl -XGET -H "Content-Type: application/json" -u "<apiKey>:<apiToken>" https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/requests`

- Para visualizar o status de uma solicitação gerenciamento de dispositivo específica:

`curl -XGET -H "Content-Type: application/json" -u "<apiKey>:<apiToken>" https://<orgID>.internetofthings.ibmcloud.com:443/api/v0002/mgmt/requests/<requestId>`

## Orientações sobre Extensões de gerenciamento de dispositivo

As orientações a seguir demonstram o fluxo que é necessário para manipular Extensões de gerenciamento de dispositivo:

- A orientação [Pacotes de Extensão de gerenciamento de dispositivo no WIoT Platform ![Ícone de link externo](../../../../icons/launch-glyph.svg "Ícone de link externo")](https://developer.ibm.com/recipes/tutorials/device-management-extension-packages-in-wiot-platform/){: new_window} fornece instruções para registrar um dispositivo gerenciado com o {{site.data.keyword.iot_short}} para que o dispositivo possa receber e manipular ações de Extensão de gerenciamento de dispositivo. As amostras de código na orientação são gravadas usando a Biblioteca do Cliente Python.

redpajama_set_name: RedPajamaGithub


text:
package com.vladsch.md.nav.psi.element;

public interface MdAutoLink extends MdLinkElement<MdAutoLinkStub>, MdStructureViewPresentableElement, MdBreadcrumbElement {

}


text: div{ color: red; }


text:
<!DOCTYPE html>

    <title>jsoup Javadoc overview</title>

jsoup: Java HTML parser that makes sense of real-world HTML soup.

jsoup is a Java library for working with real-world HTML. It provides a very convenient API
for extracting and manipulating data, using the best of DOM, CSS, and jquery-like methods.

jsoup implements the WHATWG HTML specification, and parses HTML to the same DOM
as modern browsers do.

parse HTML from a URL, file, or string

find and extract data, using DOM traversal or CSS selectors

manipulate the HTML elements, attributes, and text

clean user-submitted content against a safe white-list, to prevent XSS

output tidy HTML

jsoup is designed to deal with all varieties of HTML found in the wild; from pristine and validating,
to invalid tag-soup; jsoup will create a sensible parse tree.

See jsoup.org for downloads, documentation, and examples...

@author Jonathan Hedley


text:
var FS = require('./../FamilySearch'),
    utils = require('./../utils');

/**
 * @ngdoc function
 * @name places.types:constructor.PlaceDescription
 * @description
 *
 * Place description returned by the Place Authority.
 *
 * @param {FamilySearch} client FamilySearch sdk client
 * @param {Object} data raw object data
 */
var PlaceDescription = FS.PlaceDescription = function(client, data){
  FS.BaseClass.call(this, client, data);

  if(data){
    if(data.names){
      utils.forEach(this.data.names, function(name, i){
        if(!(name instanceof FS.TextValue)){
          this.data.names[i] = client.createTextValue(name);
        }
      }, this);
    }
  }
};

/**
 * @ngdoc function
 * @name places.functions:createPlaceDescription
 * @param {Object} data [PlaceDescription](https://familysearch.org/developers/docs/api/gx/PlaceDescription_json) data
 * @return {Object} {@link places.types:constructor.PlaceDescription PlaceDescription}
 * @description Create a {@link places.types:constructor.PlaceDescription PlaceDescription} object. Use this method instead of calling the constructor directly.
 */
FS.prototype.createPlaceDescription = function(data){
  return new PlaceDescription(this, data);
};

PlaceDescription.prototype = utils.extend(Object.create(FS.BaseClass.prototype), {

  constructor: PlaceDescription,

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getId
   * @methodOf places.types:constructor.PlaceDescription
   * @return {string} place id
   */

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getNames
   * @methodOf places.types:constructor.PlaceDescription
   * @return {TextValue[]} An array of names. The preferred value is first.
   */
  getNames: function(){ return utils.maybe(this.data.names);  },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getLang
   * @methodOf places.types:constructor.PlaceDescription
   * @return {string} The language of the Place Description. See [http://www.w3.org/International/articles/language-tags/](http://www.w3.org/International/articles/language-tags/)
   */
  getLang: function(){ return this.data.lang; },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getIdentifiers
   * @methodOf places.types:constructor.PlaceDescription
   * @return {Object} map of identifiers to arrays of values
   */
  getIdentifiers: function(){ return utils.maybe(this.data.identifiers); },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getTypeUri
   * @methodOf places.types:constructor.PlaceDescription
   * @return {string} A URI used to identify the type of a place.
   */
  getTypeUri: function(){ return this.data.type; },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getLatitude
   * @methodOf places.types:constructor.PlaceDescription
   * @return {number} Degrees north or south of the Equator (0.0 degrees). Values range from −90.0 degrees (south) to 90.0 degrees (north).
   */
  getLatitude: function(){ return this.data.latitude; },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getLongitude
   * @methodOf places.types:constructor.PlaceDescription
   * @return {number} Angular distance in degrees, relative to the Prime Meridian. Values range from −180.0 degrees (west of the Meridian) to 180.0 degrees (east of the Meridian).
   */
  getLongitude: function(){ return this.data.longitude; },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getTemporalDescription
   * @methodOf places.types:constructor.PlaceDescription
   * @return {Object} A description of the time period to which this place description is relevant.
   */
  getTemporalDescription: function(){ return utils.maybe(this.data.temporalDescription); },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getDisplay
   * @methodOf places.types:constructor.PlaceDescription
   * @return {Object} includes `name`, `fullName`, and `type` attributes
   */
  getDisplay: function(){ return utils.maybe(this.data.display); },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getName
   * @methodOf places.types:constructor.PlaceDescription
   * @return {String} The name of this place as listed in the display properties.
   */
  getName: function(){
    return this.getDisplay().name;
  },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getFullName
   * @methodOf places.types:constructor.PlaceDescription
   * @return {String} The fully qualified name (e.g. includes the name of parent jursdictions) of this place as listed in the display properties
   */
  getFullName: function(){
    return this.getDisplay().fullName;
  },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getType
   * @methodOf places.types:constructor.PlaceDescription
   * @return {String} The type as listed in the display properties.
   */
  getType: function(){
    return this.getDisplay().type;
  },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getPlaceDescriptionUrl
   * @methodOf places.types:constructor.PlaceDescription
   * @return {String} The place description's url without the access token
   */
  getPlaceDescriptionUrl: function(){
    return this.helpers.removeAccessToken(utils.maybe(this.getLink('description')).href);
  },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getJurisdictionSummary
   * @methodOf places.types:constructor.PlaceDescription
   * @description Get a summary of the jurisdiction's place description, when available. Useful
   * for place descriptions returned by {@link places.functions:getPlaceDescription} if you just
   * want the names and ids of all place descriptions in the jurisdiction chain. If you want
   * more details then use {@link places.types:constructor.PlaceDescription#getJurisdictionDetails}.
   * @return {PlaceDescription} A summary PlaceDescription for this PlaceDescription's jurisdiction.
   */
  getJurisdictionSummary: function() {
    if(this.data.jurisdiction instanceof FS.PlaceDescription){
      return this.data.jurisdiction;
    }
  },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#getJurisdictionDetails
   * @methodOf places.types:constructor.PlaceDescription
   * @description Get the full details of the jurisdiction's PlaceDescription. The promise
   * will fail if no jurisdiction is available.
   * @return {Object} A promise for the response of retrieving the details for the jursdiction
   */
  getJurisdictionDetails: function() {
    if(this.data.jurisdiction instanceof FS.PlaceDescription){
      return this.client.getPlaceDescription(this.data.jurisdiction.getPlaceDescriptionUrl());
    } else {
      return Promise.reject(new Error('No jurisdiction available'));
    }
  },

  /**
   * @ngdoc function
   * @name places.types:constructor.PlaceDescription#setJurisdiction
   * @methodOf places.types:constructor.PlaceDescription
   * @param {Object} A json object representing the new jursidication data, or a PlaceDescription object.
   * @return {PlaceDescription} this object
   */
  setJurisdiction: function(jurisdiction){
    if(!(jurisdiction instanceof FS.PlaceDescription)){
      jurisdiction = this.client.createPlaceDescription(jurisdiction);
    }
    this.data.jurisdiction = jurisdiction;
    return this;
  }

});


text:
require 'one_helper'
require 'one_helper/onequota_helper'

class OneUserHelper < OpenNebulaHelper::OneHelper
    def self.rname
        "USER"
    end

    def self.conf_file
        "oneuser.yaml"
    end

    def self.password_to_str_desc
        "User password"
    end

    def self.password_to_str(arg, options)
        if options[:read_file]
            begin
                password = File.read(arg).split("\n").first
            rescue
                return -1, "Cannot read file: #{arg}"
            end
        else
            password = arg.dup
        end

        if options[:driver] == OpenNebula::User::X509_AUTH
            require 'opennebula/x509_auth'
            password = OpenNebula::X509Auth.escape_dn(password)
        end

        if options[:sha1] || options[:driver] == OpenNebula::User::CIPHER_AUTH
            require 'digest/sha1'
            password = Digest::SHA1.hexdigest(password)
        end

        return 0, password
    end

    def password(options)
        case options[:driver]
        when OpenNebula::User::SSH_AUTH
            if !options[:key]
                return -1, "You have to specify the --key option"
            end

            require 'opennebula/ssh_auth'

            begin
                auth = OpenNebula::SshAuth.new(:private_key=>options[:key])
            rescue Exception => e
                return -1, e.message
            end
        when OpenNebula::User::X509_AUTH
            options[:cert] ||= ENV['X509_USER_CERT']

            if !options[:cert]
                return -1, "You have to specify the --cert option"
            end

            require 'opennebula/x509_auth'

            begin
                cert = [File.read(options[:cert])]
                auth = OpenNebula::X509Auth.new(:certs_pem=>cert)
            rescue Exception => e
                return -1, e.message
            end
        else
            return -1, "You have to specify an Auth method or define a password"
        end

        return 0, auth.password
    end

    def self.login(username, options)
        case options[:driver]
        when OpenNebula::User::SSH_AUTH
            require 'opennebula/ssh_auth'

            options[:key]  ||= ENV['HOME']+'/.ssh/id_rsa'

            begin
                auth = OpenNebula::SshAuth.new(:private_key=>options[:key])
            rescue Exception => e
                return -1, e.message
            end
        when OpenNebula::User::X509_AUTH
            require 'opennebula/x509_auth'

            options[:cert] ||= ENV['X509_USER_CERT']
            options[:key]  ||= ENV['X509_USER_KEY']

            begin
                certs = [File.read(options[:cert])]
                key   = File.read(options[:key])

                auth = OpenNebula::X509Auth.new(:certs_pem=>certs, :key_pem=>key)
            rescue Exception => e
                return -1, e.message
            end
        when OpenNebula::User::X509_PROXY_AUTH
            require 'opennebula/x509_auth'

            options[:proxy] ||= ENV['X509_PROXY_CERT']

            begin
                proxy = File.read(options[:proxy])

                certs = proxy.scan(/(-+BEGIN CERTIFICATE-+\n[^-]*\n-+END CERTIFICATE-+)/)
                certs.flatten!

                rc = proxy.match(/(-+BEGIN RSA PRIVATE KEY-+\n[^-]*\n-+END RSA PRIVATE KEY-+)/)
                key= rc[1]

                auth = OpenNebula::X509Auth.new(:certs_pem=>certs, :key_pem=>key)
            rescue => e
                return -1, e.message
            end
        else
            return -1, "You have to specify an Auth method"
        end

        options[:time] ||= 3600

        auth.login(username, options[:time])

        return 0, 'export ONE_AUTH=' << auth.class::LOGIN_PATH
    end

    def format_pool(options)
        config_file = self.class.table_conf

        table = CLIHelper::ShowTable.new(config_file, self) do
            def pool_default_quotas(path)
                @data.dsearch('/USER_POOL/DEFAULT_USER_QUOTAS/'+path)
            end

            def quotas
                if !defined?(@quotas)
                    quotas = @data.dsearch('USER_POOL/QUOTAS')
                    @quotas = Hash.new

                    if (!quotas.nil?)
                        quotas = [quotas].flatten

                        quotas.each do |q|
                            @quotas[q['ID']] = q
                        end
                    end
                end
                @quotas
            end

            column :ID, "ONE identifier for the User", :size=>4 do |d|
                d["ID"]
            end

            column :NAME, "Name of the User", :left, :size=>15 do |d|
                d["NAME"]
            end

            column :GROUP, "Group of the User", :left, :size=>10 do |d|
                helper.group_name(d, options)
            end

            column :AUTH, "Auth driver of the User", :left, :size=>8 do |d|
                d["AUTH_DRIVER"]
            end

            column :VMS , "Number of VMS", :size=>9 do |d|
                begin
                    q = quotas[d['ID']]
                    limit = q['VM_QUOTA']['VM']["VMS"]

                    if limit == OneQuotaHelper::LIMIT_DEFAULT
                        limit = pool_default_quotas("VM_QUOTA/VM/VMS")
                        if limit.nil? || limit == ""
                            limit = OneQuotaHelper::LIMIT_UNLIMITED
                        end
                    end

                    if limit == OneQuotaHelper::LIMIT_UNLIMITED
                        "%3d /   -" % [q['VM_QUOTA']['VM']["VMS_USED"]]
                    else
                        "%3d / %3d" % [q['VM_QUOTA']['VM']["VMS_USED"], limit]
                    end

                rescue NoMethodError
                    "-"
                end
            end

            column :MEMORY, "Total memory allocated to user VMs", :size=>17 do |d|
                begin
                    q = quotas[d['ID']]
                    limit = q['VM_QUOTA']['VM']["MEMORY"]

                    if limit == OneQuotaHelper::LIMIT_DEFAULT
                        limit = pool_default_quotas("VM_QUOTA/VM/MEMORY")
                        if limit.nil? || limit == ""
                            limit = OneQuotaHelper::LIMIT_UNLIMITED
                        end
                    end

                    if limit == OneQuotaHelper::LIMIT_UNLIMITED
                        "%7s /       -" % [
                            OpenNebulaHelper.unit_to_str(q['VM_QUOTA']['VM']["MEMORY_USED"].to_i,{},"M")]
                    else
                        "%7s / %7s" % [
                            OpenNebulaHelper.unit_to_str(q['VM_QUOTA']['VM']["MEMORY_USED"].to_i,{},"M"),
                            OpenNebulaHelper.unit_to_str(limit.to_i,{},"M")]
                    end

                rescue NoMethodError
                    "-"
                end
            end

            column :CPU, "Total CPU allocated to user VMs", :size=>11 do |d|
                begin
                    q = quotas[d['ID']]
                    limit = q['VM_QUOTA']['VM']["CPU"]

                    if limit == OneQuotaHelper::LIMIT_DEFAULT
                        limit = pool_default_quotas("VM_QUOTA/VM/CPU")
                        if limit.nil? || limit == ""
                            limit = OneQuotaHelper::LIMIT_UNLIMITED
                        end
                    end

                    if limit == OneQuotaHelper::LIMIT_UNLIMITED
                        "%3.1f /   -" % [q['VM_QUOTA']['VM']["CPU_USED"]]
                    else
                        "%3.1f / %3.1f" % [q['VM_QUOTA']['VM']["CPU_USED"], limit]
                    end

                rescue NoMethodError
                    "-"
                end
            end

            column :PASSWORD, "Password of the User", :size=>50 do |d|
                d['PASSWORD']
            end

            default :ID, :NAME, :GROUP, :AUTH, :VMS, :MEMORY, :CPU
        end

        table
    end

    private

    def factory(id=nil)
        if id
            OpenNebula::User.new_with_id(id, @client)
        else
            xml=OpenNebula::User.build_xml
            OpenNebula::User.new(xml, @client)
        end
    end

    def factory_pool(user_flag=-2)
        #TBD OpenNebula::UserPool.new(@client, user_flag)
        @user_pool = OpenNebula::UserPool.new(@client)
        return @user_pool
    end

    def format_resource(user, options = {})
        system = System.new(@client)

        str="%-16s: %-20s"
        str_h1="%-80s"

        CLIHelper.print_header(str_h1 % "USER #{user['ID']} INFORMATION")
        puts str % ["ID",          user.id.to_s]
        puts str % ["NAME",        user.name]
        puts str % ["GROUP",       user['GNAME']]
        groups = user.retrieve_elements("GROUPS/ID")
        puts str % ["SECONDARY GROUPS", groups.join(',') ] if groups.size > 1
        puts str % ["PASSWORD",    user['PASSWORD']]
        puts str % ["AUTH_DRIVER", user['AUTH_DRIVER']]

        puts str % ["ENABLED",
            OpenNebulaHelper.boolean_to_str(user['ENABLED'])]

        puts

        CLIHelper.print_header(str_h1 % "USER TEMPLATE",false)
        puts user.template_str

        user_hash = user.to_hash

        default_quotas = nil

        user.each('/USER/DEFAULT_USER_QUOTAS') { |elem|
            default_quotas = elem
        }

        helper = OneQuotaHelper.new
        helper.format_quota(user_hash['USER'], default_quotas)
    end
end


text:
/*
 tnt.js 基于miniui和jquery的高级封装
 */

(function(root, factory) {
    // 生成ebapBase
    var ebapBase = factory();
    root.ebapBase = ebapBase || {};
    // umd格式
    if (typeof define === 'function' && define.amd) {
		define(function () {
            return ebapBase;
		})
	} else if (typeof exports === 'object') {
		if (module !== 'undefined' && module.exports) {
			exports = module.exports = ebapBase;
		}
		exports.ebapBase = ebapBase;
	}
})(typeof window === 'object' && window, function () {
    // 快捷方法
    var nativeToString = Object.prototype.toString;
    var nativeSlice = Array.prototype.slice;
    var nativeHasOwn = Object.prototype.hasOwnProperty;

    var ebapBase = (function() {
    var ebapModules = {};
    var ebapInstance = null;
    var isParsed = false;
    var winLoc = window.location;
    var winLocSearch = winLoc.search;
    var guid = 0;
    var win = window;
    var commonCfg = {
    };
    var topices = {};
    var localCfg = {
        'url': '当前页面地址:',
        'key': '错误配置的key:',
        'modules': '模块详情:'
    }
    /*
     配置文件
     * */
    var config = {
        root: window['ctx'],
        injectRules: {
            'normal': function() {
                rules['mixin'][0][rules.method]();
            },
            'ifelse': function(rules) {
                if (rkFlist.mode = 'line-add') {
                    rules['mixin'][0][rules.method]();
                } else {
                    rules['mixin'].forEach(function(i, f) {
                        if (i >= 1) {
                            f[rules.method]()
                        }
                    });
                }
            },
            'combine': function() {
                rules['mixin'].forEach(function(i, f) {
                    f[rules.method]()
                });
            }
        },
        uiLib: 'mini',
        nameSpace: 'ebap',
        enableList: {
            open: true,
            decode: true,
            encode: true,
            utils: {
            },
            lock: ['get', 'created']
        },
        $$type: '',
        openFilterRules: ['onload', 'ondestroy']
    };
    var _params = {}
    // 判断某个环境下是否存在某个库是否支持某个方法
    function support(libName,funcName,context) {
        var __context = context ? context : window;
        return (typeof __context[libName] !=='undefined') && __context[libName][funcName];
    }
    // 判断miniui是否支持某个方法
    function miniSupport(methodName,options) {
        if (config.uiLib === 'mini' && support('mini', 'get')) {
            if ( methodName === 'form' ) {
                return new mini.Form(options.id)
            } else if (methodName === 'tooltip') {
                return new mini.ToolTip();
            } else if (methodName === 'contextMenu') {
                return new mini.contextMenu();
            }
        }
        return support(config.uiLib, methodName);
    }
    /**
     * 执行某个对象上的某个方法,也可以注入参数
     * @param {node} elm
     * @param {string} method
     * @returns
     */
    function _execute(elm,method) {
        var _method = method;
        var arg = Array.prototype.slice.call(arguments,2);
        return elm[_method] && elm[_method].apply(this,arg);
    }
    /**
     * 判断某个特定的dom元素是否存在
     * @param {any} elm
     * @param {any} targetInfo
     * @returns
     */
    function _isExistTarget(elm,targetInfo) {
        if (elm.tagName.toUpperCase() === targetInfo.tagName.toUpperCase() && elm.className.indexOf(targetInfo.cls) !== -1 || elm.id === targetInfo.id) {
            return true;
        }
        return false
    }
    /**
     * 事件代理
     * @param {domNode} proxyNode
     * @param {object} targetInfo
     * @param {function} callback
     * @param {string} eventType
     */
    function _eventProxy(proxyNode, targetInfo, callback, eventType) {
        var proxyArgs = [].slice.call(arguments);
        var proxyNode = proxyNode;
        var targetInfo = targetInfo;
        var eventType = eventType || 'click';
        var callback = callback;
        if (proxyArgs.length === 1 && nativeToString.call(proxyArgs[0]) === '[object Object]') {
            proxyNode = proxyArgs[0].context;
            targetInfo = {
                cls: proxyArgs[0].cls,
                tagName: proxyArgs[0].tagName,
                id: proxyArgs[0].id
            };
            eventType = proxyArgs[0].eventType || 'click';
            callback = proxyArgs[0].cb;
        }
        proxyNode.on(eventType, function(e) {
            if (e.target.tagName === 'A' && targetInfo.tagName === 'a') {
                e.preventDefault();
            }
            if (_isExistTarget(e.target, targetInfo)) {
                targetInfo = $.extend({}, targetInfo, { level: 0, dom: e.target});
                callback(targetInfo);
                return undefined
            }
            $(e.target).parents(proxyNode).each(function(idx,elm) {
                if (_isExistTarget(elm, targetInfo)) {
                    targetInfo = $.extend({}, targetInfo, { level: idx+1,dom: e.target});
                    callback(targetInfo)
                    //忽略后续的比较 跳出each函数 from http://www.jb51.net/article/50711.htm
                    return false;
                }
            });
        })
    }
    /**
     * 说明: 自动获取指定区域的input,textarea的值并将其加入到ebapparams
     * @param  {jquery object} $els
     * @param {object} bccparams
     **/
    function autoInput($els, ebapparams) {
        $els.on('input', function(event) {
            if (event.target.value.length === 0) {
                delete ebapparams[event.target.name];
            } else {
                ebapparams[event.target.name] = event.target.value;
            }
        });
        if (document.all) {
            $els.each(function() {
                var that = this;
                if (this.attachEvent) {
                    this.attachEvent('onpropertychange', function(e) {
                        if (e.propertyName != 'value') return;
                        $(that).trigger('input');
                    });
                }
            });
        }
    };
    /**
     * 说明: 对multiselect组件onchange事件的封装
     * @param {object} options
     * @param {boolean} checked
     * @param {element} select
     * @param {object} bccparams
     **/
    function multiChangeHandler(option, checked, key, ebapparams) {
        var _multiKey = key
        if (checked) {
            ebapparams[_multiKey] = option[0].value;
        } else {
            ebapparams[_multiKey] = '';
        }
    }
    // 初始化设置
    function  setUp (func) {
        typeof func === 'function' && func.apply(null, nativeSlice.call(arguments, 1));
        return this;
    }
    var _cacheEbapIns = null;
    /**
     * 说明: 项目常用的工具方法
     **/
    // https://github.com/goatslacker/get-parameter-names/blob/master/index.js
    // 看不懂正则的,可以上https://regexper.com
    function getParameterNames(fn) {
        var COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
        var DEFAULT_PARAMS = /=[^,]+/mg;
        var FAT_ARROWS = /=>.*$/mg;
        var code = fn.toString()
            .replace(COMMENTS, '')
            .replace(FAT_ARROWS, '')
            .replace(DEFAULT_PARAMS, '');

        var result = code.slice(code.indexOf('(') + 1, code.indexOf(')'))
            .match(/([^\s,]+)/g);

        return result === null
            ? []
            : result;
    }
    // 对object单个或多个key进行分析,分析完成后,执行相应的回调
    function getAllOptions(options) {
        return function (path, func, defaultOpts) {
            var optionsStrToArr = [];
            var result = null;
            var defaultValue = null;
            var oLen = null;
            if (path && typeof path === 'string' && path.length > 0) {
                if (typeof path === 'string') {
                    optionsStrToArr = path.split('.');
                    oLen = optionsStrToArr.length;
                }
                for (var _index=0;_index< oLen; _index++) {
                    if (result) {
                        result = result[optionsStrToArr[_index]];
                    } else {
                        result = options[optionsStrToArr[_index]];
                    }
                }
                if (func && typeof func === 'function') {;
                    defaultValue = func.call(null, result, defaultOpts);
                } else {
                    defaultValue = func;
                }
                return result || defaultValue;
            } else if (nativeToString.call(path) === '[object Array]') {
                var plen = path.length;
                var pstr = '';
                var pResult = [];
                for (var p = 0; p <plen; p++) {
                    pstr = path[p];
                    result = null;
                    if (typeof pstr === 'string') {
                        optionsStrToArr = pstr.split('.') || [];
                        oLen = optionsStrToArr.length || 0;
                    }
                    for (var _index = 0;_index< oLen; _index++) {
                        if (result) {
                            result = result[optionsStrToArr[_index]];
                        } else {
                            result = options[optionsStrToArr[_index]];
                        }
                    }
                    pResult.push(result);
                }
                pResult.push(defaultOpts, path);
                if (func && typeof func === 'function') {
                    defaultValue = func.apply(null, pResult);
                } else {
                    defaultValue = func;
                }
                return pResult || defaultValue;
            }
        }
    }
    var utilsPool = {};
    // pubsub模式消息通信,参考https://github.com/mroderick/PubSubJS
    var customEventIndex = -1;
    var pubsub = {
        _on: function (topic, cb, context) {
            if (!topices[topic]) {
                topices[topic] = [];
            }
            // 生成唯一的token,便于后期取消
            var token = config.nameSpace + '-uid-' + (customEventIndex++);
            topices[topic].push({
                context: context,
                cb: cb,
                token: token
            });
            return token;
        },
        _clearAll: function () {
            topices = {};
        },
        _clear: function (topic) {
            if (topices[topic]) {
                delete topices[topic]
            }
        },
        _off: function (value) {
            var descendantTopicExists = function (topic) {
                for (var t in topices) {
                    if (nativeHasOwn.call(topices, t) && t.indexOf(topic) === 0) {
                        return true;
                    }
                }
                return false;
            };
            var isTopic = typeof value === 'string' && (nativeHasOwn.call(topices, value) || descendantTopicExists(value));
            var isToken = !isTopic && typeof value === 'string';
            var isFunction = typeof value === 'function';
            var t = null;
            var result = true;
            var topic = null;
            if (isTopic) {
                pubsub._clear(value);
                return;
            }
            for (t in topices) {
                if (nativeHasOwn.call(topices, t)) {
                    topic = topices[t];
                    for (var i = 0, tl= topic.length; i < tl; i++) {
                        if (isToken && topic[i].token === value) {
                            topic.splice(i, 1);
                            result = value;
                        } else if (isFunction && topic[i].cb === value) {
                            topices[t].splice(i, 1);
                            result = true;
                        }
                    }
                }
            }
            return result;
		},
        _once: function (topic, cb) {
            if (!topices[topic]) {
                topices[topic] = [];
            }
            topices[topic].push({
                context: this,
                cb: cb,
                once: true
            })
        },
        _trigger: function (topic, data, async) {
            if (!nativeHasOwn.call(topices, topic)) {
                return;
            }
            function throwException (ex) {
                return function rethrowException() {
                    throw ex;
                }
            }
            function callSubscriberWithExceptions( subscriber, data, async ) {

                function emitSubscribe(data) {
                    if (subscriber.cb) {
                        subscriber.cb.call(subscriber.context, data);
                    }
                    if (subscriber.once) {
                        subscriber.cb = function () {}
                    }
                }

                if (async === true) {
                    try {
                        emitSubscribe(data);
                    } catch (err) {
                        setTimeout(throwException(err), 0);
                    }
                }

                emitSubscribe(data);
            }

            function distributeMsg () {
                if (nativeHasOwn.call(topices, topic)) {
                    var subscribers = topices[topic];
                    var cbLen = subscribers.length;
                    for (var i = 0 ; i < cbLen; i++) {
                        callSubscriberWithExceptions(subscribers[i], data, async);
                    }
                }
            }
            if (async === true) {
                setTimeout(distributeMsg, 0);
            } else {
                distributeMsg();
            }
            return true;
        }
    }
    var utils = {
        actionTypes: ['ebap-tbActionAdd','ebap-tbActionDelete','ebap-tbActionModify','ebap-tbActionAssign','ebap-actionType'],
        toggleEnable: function(obj) {
            $.extend(config['enableList'], obj);
        },
        // 错误信息提示
        invarint: function (info, type) {
            for (var i in info) {
                console[type || 'error'](localCfg[i], info[i]);
            }
        },
        now: function() {
            return new Date();
        },
        throttle: function (func, wait, options) {
            var context = null;
            var timeId = null;
            var args = null;
            var previous = 0;
            var result = null;
            var later = function () {
                previous = options.leading === true ? 0 : utils.now();
                timeId = null;
                result = func.apply(context, args);
                if (!timeId) {
                    context = args = null;
                }
            }
            return function () {
                var now = utils.now();
                args = arguments;
                if (!previous || options.leading === false) {
                    previous = utils.now();
                }
                var remaining = wait - (now - previous);
                if (remaining < 0 || remaining> wait) {
                    if (timeId) {
                        clearTimeout(timeId);
                        timeId = null;
                    }
                    result = func.apply(context, args);
                    if (!timeId) {
                        context = args = null;
                    }
                } else if (!timeId && options.trailing  !== false) {
                    timeId = setTimeout(later, remaining);
                }
                return result;
            }
        },
        getNormalDate: function (time) {
            var startTime = null;
            if (typeof startTime === 'number') {
                startTime = new Date(time);
            } else if (typeof startTime === 'string') {
                startTime = new Date(Date.parse(time));
            }
            return startTime;
        },
        setParams: function(key, value) {
            if (key && nativeToString.call(key) == '[object Object]') {
                $.each(key, function(m, ms) {
                    if (m && ms) {
                        _params[m] =  ms;
                    }
                })
            } else {
                if (key) {
                    _params[key] = value;
                }
            }
        },
        getParams: function (key) {
            if (key && _params[key]) {
                return _params[key];
            }
        },
        hasKeys: function (obj) {
            if (typeof obj === 'object' && !!obj && nativeToString.call(obj) === '[object Object]') {
                for (var o in obj) {
                    if (nativeHasOwn.call(obj, o)) {
                        return true;
                    }
                }
            }
            return false;
        },
        hasAndReturnGetTime: function (time) {
            return time && time.getTime && typeof time.getTime === 'function';
        },
        computeDelta: function (startTime, endTime) {
            var startTime = utils.getNormalDate(startTime);
            var endTime = utils.getNormalDate(endTime);
            var deltaTime = null;
            if (hasAndReturnGetTime(startTime) && hasAndReturnGetTime(endTime)) {
                var deltaTime = startTime.getTime() - endTime.getTime();//时间差的毫秒数
            }
            deltaTime = Math.abs(deltaTime);
            //计算出相差天数
            var days=Math.floor(deltaTime/(24*3600*1000))
            //计算出小时数
            var leave1=deltaTime%(24*3600*1000);
            //计算天数后剩余的毫秒数
            var hours=Math.floor(leave1/(3600*1000))
            //计算相差分钟数
            var leave2=leave1%(3600*1000);
            //计算小时数后剩余的毫秒数
            var minutes=Math.floor(leave2/(60*1000))

            //计算相差秒数
            var leave3=leave2%(60*1000);
            //计算分钟数后剩余的毫秒数
            var seconds=Math.round(leave3/1000);
            return {
                days: days,
                hours: hours,
                minutes: minutes
            };
        },
        /*
          生成深层依赖分析函数
        */
        genDpo: function (context,opts, options) {
            var po = typeof options === 'object' ? utils.getAllOptions(options) : options;
            if (context && context.genParseOBK && context['$$type'] === config.nameSpace) {
                return context.genParseOBK($.extend(opts || {}, {
                    parseOBK: po
                }))
            }
        },
        // 当获取模块失败时, 提供友好的错误信息提示
        safeGetModule: function (modules, options, moduleSettings) {
            try {
                var moduleIns = utils.getModule(ebapModules, options.key);
                var waitInject = {};
                moduleIns && typeof moduleIns === 'function' && (waitInject['$$type'] = config.nameSpace);
                return $.extend(true, moduleIns($.extend({}, options)), {
                    setUrls: utils.setUrls,
                    genParseOBK: utils.genParseOBK,
                    parseOBK: utils.getAllOptions(options),
                    getDepsIns: utils.getDepsIns,
                    extend: utils.extend,
                    getIns: utils.getIns,
                    insId: options.key === 'smodules' ? options.id : '',
                    moduleType: options.mType || options.key,
                    moduleDeps: options.moduleDeps
                }, moduleSettings, waitInject, pubsub);
            } catch (e) {
                utils.invarint({
                    url: window.location.href,
                    key: options.key,
                    modules: modules
                });
                return;
            }
        },
        // 从列表数据中生成url后缀
        genUrls: function(originData, data, rules) {
            var hasIdFlag = data.indexOf('id=') > -1;
            var hasSearchFlag =  data.indexOf('?') > -1;
            var removeInfo = {};
            var odLen = originData.length;
            for (var i = 0; i < odLen; i++) {
                var r = originData[i];
                $.each(rules, function(i, dt) {
                    if (nativeHasOwn.call(r,dt)) {
                        if (!removeInfo[dt]) {
                            removeInfo[dt] = dt + '='+ r[dt]
                        } else {
                            removeInfo[dt] +=',' +  r[dt]
                        }
                    }
                })
            }
            hasIdFlag && (data += (hasSearchFlag ? removeInfo['id'].slice(3) : '?'+removeInfo['id'].slice(3)));
            for (var rinfo in removeInfo) {
                if (nativeHasOwn.call(removeInfo, rinfo)) {
                    if (hasIdFlag) {
                        rinfo !== 'id' && (data += ('&'+removeInfo[rinfo]))
                    } else {
                        data += (hasSearchFlag ? removeInfo[rinfo] + '&' : '?'+removeInfo[rinfo] + '&');
                    }
                }
            }
            return data;
        },
        doDel: function (originData, data, rules) {
            var data = utils.genUrls(originData, data, rules);
            utils.doListAjax.call(this, data);
        },
        doListAjax: function (url) {
            var self = this;
            utils.ajax({
               url: url,
               success: function (text) {
                   self.getIns().reload();
               },
               error: function () {
               }
            });
        },
        getAllOptions: getAllOptions,
        disable: function (key) {
            var _methodName = key;
            if (utils[_methodName]) {
                config.enableList.utils[_methodName] = false;
            }
        },
        setNameSpace: function (ns) {
            if (!ns) return;
            return config['nameSpace'] = typeof ns === 'string' ? ns: ns.toString();
        },
        setPropTrue: function (obj) {
            if (!$.isPlainObject(obj)) return;
            for (var u in obj) {
                if (nativeHasOwn.call(obj, u) && typeof obj[u] == 'function' && $.inArray(u, config.enableList.lock) == -1) {
                    config.enableList.utils[u] = true;
                }
            }
        },
        // 通过id获取某个miniui实例
        getInstance: function(options, type) {
            var cacheInstance = null;
            if (typeof options === 'string') {
                var options = {
                    id: options
                }
            }
            if (type) {
                cacheInstance = utils.created(options, String(type));
            } else {
                cacheInstance = utils.created(options);
            }
            return cacheInstance;
        },
        get: get,
        genOpenCfg: function(openCfg) {
            var _cfg = {};
            $.each(openCfg, function(i, cfg) {
                if ($.inArray(cfg['filter'] || cfg.openFilterRules, i) > -1) {
                    if (i === 'onload') {
                        _cfg[i] = cfg[i];
                    } else {
                        _cfg[i] = function(action) {
                            action ? cfg[i](action) : cfg[i]();
                        }
                    }
                }
                _cfg[i] = cfg[i];
            })
            return _cfg;
        },
        open: function(openCfg) {
            console.log(":::openCfg", openCfg);
            // var newOpenCfg = utils.genOpenCfg(openCfg);
            miniSupport('open')(openCfg);
        },
        genDepsIns: function (deps,flag) {
            var _deps = {};
            var deps = (deps && deps.length>=0) ? deps : [];
            var depsKey = '';
            for (var d = 0, dl = deps.length; d < dl; d++) {
                depsKey = deps[d].key.split('.').join('');
                if (flag) {
                    _deps[depsKey] = utils.getInstance(deps[d])
                } else {
                    _deps[depsKey] = utils.get(deps[d])
                }
            }
            return _deps;
        },
        created: function(options, methodName) {
            var _cacheEbapIns = null;
            if (typeof methodName === 'string' && methodName === 'form') {
                _cacheEbapIns = miniSupport('form', options);
            } else {
                _cacheEbapIns = miniSupport('get')(options.id);
            }
            if (_cacheEbapIns) {
                options['created'] && typeof options['created'] === 'function' && options['created'](_cacheEbapIns, options.moduleDeps)
            }
            return _cacheEbapIns;
        },
        seekOptions: function(options, ins) {
            for (var o in options) {
                if (typeof options[o] === 'function') {
                    options[o](ins);
                }
            }
        },
        isAandHasCls:function(target,clsStr,strategy) {
            return target.tagName === 'A' && $(target).hasClass(clsStr) && clsStr === strategy;
        },
        // 自动绑定事件,并执行相应的策略,用于表格中事件处理
        extendInjectRules: function (rule) {
            if ($.isPlainObject(rule)) {
                for (var r in rule) {
                    if (nativeHasOwn.call(rule, r)) {
                        config.injectRules[r] = rule[r]
                    }
                }
                return true;
            }
            return false;
        },
        // 动态加载脚本
        loadScript: function(src, cb, func) {
            var spt = null;
            if (typeof src === 'string') {
                spt = document.createElement('script');
                spt.charset="utf-8";
                spt.src = src;
                spt.onload = spt.onreadystatechange =  function(e) {
                    if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
                        cb(e);
                        spt.onload = spt.onreadystatechange = null;
                    }
                }
                func(spt);
            } else if (nativeToString.call(src) === '[object Array]') {
                var slen = src.length;
                var count = slen;
                var argsArr = [];
                for (var i = 0; i< slen; i++) {
                    spt = document.createElement('script')
                    spt.charset="utf-8";
                    spt.src = src[i];
                    spt.onload = spt.onreadystatechange =  function(e) {
                        argsArr.push(e);
                        if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
                            count--;
                            if (!count) {
                                cb(argsArr);
                            }
                            spt.onload = spt.onreadystatechange = null;
                        }
                    }
                    func(spt);
                }
            }
        },
        eventProxy: _eventProxy,
        autoProxyTrigger: function(cfg) {
            for (var icfg in cfg) {
                if (nativeHasOwn.call(cfg, icfg)) {
                    this.eventProxy({
                        context: cfg[icfg].context,
                        cls: icfg,
                        tagName: cfg[icfg].tagName,
                        eventType: cfg[icfg].eventType,
                        cb:  cfg[icfg].cb
                    });
                }
            }
        },
        getIns: function() {
            var insId = this.insId || '';
            var moduleType = this.moduleType;
            if (!insId) {
                return this;
            }
            return utils.getInstance({ id: insId }, moduleType);
        },
        setCommonCfg: function(obj, deep) {
            var parseOBK = getAllOptions(obj);
            var cdArr = null;
            var cdLen = null;
            $.each(commonCfg.disable, function(index, cd) {{
                if (parseOBK(cd) != null) {
                    cdArr = cd.split('.');
                    cdLen = cdArr.length;
                    if (cdLen === 1) {
                        delete obj[cdArr[0]];
                    } else if (cdLen === 2) {
                        delete obj[cdArr[0]][cdArr[1]];
                    } else if (cdLen === 3) {
                        delete obj[cdArr[0]][cdArr[1]][cdArr[2]];
                    }
                }
            }
            });
            commonCfg = $.extend(deep ? deep : true,commonCfg, obj);
        },
        getCommonCfg: function () {
            return commonCfg;
        },
        hackIe: function (verStr, func) {
            if ($.inArray(verStr.split(','), document.documentMode.toString()) !== -1) {
                func.apply(null, nativeSlice.call(arguments).length>2 && nativeSlice.call(arguments, 2))
            }
        },
        inject: function(options) {
            return function() {
                config.injectRules[options.rule](options.mixin)
            }
        },
        extend: function () {
            var _extendObj = {};
            $.each( Array.prototype.slice.call(arguments), function(i, arg) {
                _extendObj = $.extend(_extendObj, arg);
            })
            $.extend(this, _extendObj);
            return this;
        },
        //获取字典标签 ebapBase.utils.getDictLabel
        getDictLabel: function getDictLabel(data, value, defaultValue){
            for (var i=0; i<data.length; i++){
                var ebapDictRows = data[i];
                if (ebapDictRows.value == value){
                    return ebapDictRows.label;
                }
            }
            return defaultValue;
        },
        genParseOBK: function (opts) {
            // 获取当前options分析
            var parseOBK = opts.parseOBK;
            // 从参数形成新的options
            var _parseOBK = ebapUtils.getAllOptions(opts || {});
            var parseResult = [];
            return function(longPath,defaultValue) {
                var _args = [].slice.call(arguments);
                // console.clear();
                if (typeof longPath === 'string') {
                    var _key = longPath.split('.').length>=2 ? longPath.split('.').slice(1).join('.') : longPath.split('.').slice()[0] || '';
                    return _parseOBK(_key, function(result) {
                        if (result) {
                            if (typeof defaultValue === 'function') {
                                defaultValue(result,_args[2]);
                            }
                        } else {
                            return parseOBK(longPath, defaultValue, _args[2]);
                        }
                    });
                } else if (nativeToString.call(longPath) === '[object Array]') {
                    var len = longPath.length;
                    for (var l = 0; l< len; l++) {
                        var lstr = longPath[l];
                        var _key = lstr.split('.').length>=2 ? lstr.split('.').slice(1).join('.') : lstr.split('.').slice()[0] || '';
                        var _result = _parseOBK(_key, function(result) {
                            if (result) {
                                return result;
                            } else {
                                return parseOBK(lstr);
                            }
                        });
                        parseResult.push(_result);
                    }
                    parseResult.push( _args[2], longPath);
                    if (typeof defaultValue === 'function') {
                        defaultValue.apply(null, parseResult);
                    }
                    return parseResult;
                }
            }
        },
        autoInput: autoInput,
        // 设置实例的urls
        setUrls: function(obj) {
            console.log(obj);
            if (nativeToString.call(obj) === '[object Object]') {
                for ( var ukType in obj) {
                    if (ukType.toLowerCase().slice(-3) === 'url') {
                        this.settings && (this.settings[ukType] = utils.prefixPath(obj[ukType]));
                    } else {
                        this.settings && (this.settings[ukType + 'Url'] = utils.prefixPath(obj[ukType]));
                    }
                }
            }
        },
        resetRoot: function (root) {
            root && (config['root'] = root);
        },
        // 判断miniui是否支持编码
        encode: support('mini', 'encode') ?support('mini', 'encode') : function () {},
        // 判断miniui是否支持解码
        decode:support('mini', 'decode')? support('mini', 'decode') : function () {},
        clone: support('mini', 'clone') ? support('mini', 'clone'): function () {},
        // 自动为url加入根路径ctx
        prefixPath: function (url, ctx) {
            return typeof config.root !== 'undefined' ? config.root + (url || '') : ( url || '')
        },
        isString: function (str) {
            return typeof str === 'string' && str;
        },
        isSupportStoreByType: function (type) {
            var storeMap = {
                'session': window.sessionStorage,
                'local': window.localStorage,
                'cookie': document.cookie
            }
            return storeMap[utils.isString(type).toLowerCase()];
        },
        getModule: function (ns, ns_string) {
            var parts = ns_string.split('.');
            var parent = ns;
            var pl = parts.length;
            var exportModule = null;
            for (var i = 0; i < pl; i++) {
                if (!exportModule) {
                    exportModule = parent[parts[i]];
                } else {
                    exportModule = exportModule[parts[i]];
                }
            }
            return exportModule;
        },
        // 封装ajax进行更多控制
        ajax: function (options) {
            var ajaxOpts = $.extend({
                contentType: "application/json",
                dataType: 'json',
                cache: false,
                success: function ( data, textStatus, jqXHR ) {
                    options.success && options.success(data, textStatus, jqXHR);
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    options.error && (options.error(jqXHR, textStatus, errorThrown));
                }
            }, options);
            $.ajax(ajaxOpts);
        },
        // 通用的交互操作
        actions: {
            close: function (action, ebapFormIns, context ,data) {
                if (action == 'close' && ebapFormIns.isChanged()) {
                    if (confirm("数据被修改了,是否先保存?")) {
                        return false;
                    }
                }
                if (window.CloseOwnerWindow) {
                    return window.CloseOwnerWindow(action);
                } else {
                    window.close();
                }
            }
        },
        support: support,
        miniSupport: miniSupport
    };
    var ebapUtils = utils;
    // 如果页面超时,将页面重置到登录页
    function loginOut(url) {
        if (winLocSearch.length === 0 && win == win.parent) {
            win.location.herf = utils.prefixPath(url);
        } else if (winLocSearch.length === 0 && win != win.parent) {
            win = win.top;
            win.location.reload();
        }
    }
    /*
     *  登入登出控制
     * */
    var ebapLogin = function (options) {
        var loginUrl = options.url || '/a/login';
        var self = {
            out: function() {
                loginOut(loginUrl);
            }
        }
        return self;
    }
    // 集合模块
    var ebapSameModules = function (options) {
        var parseOBK = ebapUtils.getAllOptions(options);
        var allModules = {};
        var baseFields = {}
        parseOBK(['ids', 'count','names', 'mType', 'allOptions'], function(ids, count, names, mType, allOptions) {
            if (!ids) {
                for (var ic = 0; ic < count; ic++) {
                    baseFields['id'] = id;
                    baseFields['key'] = mType;
                    baseFields = $.extend(true, allOptions && allOptions[i] || $.extend(options,{
                        created: null,
                        mounted: null,
                        deps: []
                    }), baseFields);
                    allModules[names[i] || i] = utils.get(baseFields);
                    baseFields = {};
                }
            } else {
                $.each(ids, function (i,id) {
                    baseFields['id'] = id;
                    baseFields['key'] = mType;
                    baseFields = $.extend(true, allOptions && allOptions[i] || $.extend(options,{
                        created: null,
                        mounted: null,
                        deps: []
                    }), baseFields);
                    allModules[names[i] || i] = utils.get(baseFields);
                    baseFields = {};
                });
            }
        })
        var self = {
            get: function (name) {
                return allModules[name];
            }
        }
        return self;
    }
    // ajax 模块
     function ebapAjax (options) {
        var defaultOpts = {
            url: 'http://localhost:3001/users',
            method: 'get',
            data: null,
            success: function (success, status, xhr) {

            },
            complete: function(xhr, status) {

            }
        };
        var options = $.extend(defaultOpts, options);
        var localProtocol = window.location.protocol;
        var rLocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/;
        var isLocal = rLocalProtocol.test(localProtocol);
        function createStandardXHR() {
            try {
                return new window.XMLHttpRequest();
            } catch( e ) {}
        }

        function createActiveXHR() {
            try {
                return new window.ActiveXObject( "Microsoft.XMLHTTP" );
            } catch( e ) {}
        }
        function createXHR() {
            return !isLocal && createStandardXHR() || createActiveXHR();
        }
        var xhr = createXHR();
        var result = null;
        var dataType = null;
        var allResHeaders = null;
        var self = {
            start: function (opts) {
                // 生成深度依赖
                var dpo = utils.genDpo(self, opts, options);
                dpo(['method','success', 'data', 'url', 'dataType'], function(method, successCb, data, url, dataType) {
                    dataType = dataType || 'json';
                    xhr.open(method, url);
                    xhr.setRequestHeader('Cache-Control', 'max-age=3000,public');
                    xhr.onreadystatechange = function () {
                        if (xhr.readyState === 4) {
                            if (xhr.status>= 200 && xhr.status <300 || xhr.status === 304) {
                                if (xhr.getResponseHeader('Content-Type').indexOf('text/json') !== -1 &&dataType === 'json' && JSON.parse ) {
                                    result = JSON.parse(xhr.responseText);
                                } else {
                                    result = xhr.responseText;
                                }
                                successCb(result, xhr.status, xhr);
                            }
                        }
                    }
                    xhr.withCredentials = true;
                    if (method && method === 'post') {
                        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencode')
                    }
                    xhr.send(data || null);
                });
            },
            abort: function () {
                xhr.abort();
            }
        }
        return self;
    }
    // 存储模块
    function ebapStore(options) {
        var parseOBK = ebapUtils.getAllOptions(options);
        var type = parseOBK('storeType');
        var store = ebapUtils.isSupportStoreByType('local');
        var self = {
            get: function (key) {
                if (store && 'sessionlocal'.indexOf(type) !== -1 ) {
                    return store.getItem(key)
                }
            },
            set: function(key, value) {
                console.log('key::::', key, value);
                if (store && 'sessionlocal'.indexOf(type) !== -1 ) {
                    console.dir(store);
                    return store.setItem(key, value);
                }
            },
            remove: function (key) {
                if (store && 'sessionlocal'.indexOf(type) !== -1 ) {
                    return store.removeItem(key);
                }
            },
            clearAll: function (key) {
                if (store && 'sessionlocal'.indexOf(type) !== -1 ) {
                    return store.clear();
                }
            },
            each: function (func) {

            },
            on: function(eventType, func) {
                window.addEventListener(eventType, func, false);
            }
        }
        return self;
    }
    var builtInModules = builtInModules || {
            'login': ebapLogin,
            'ajax': ebapAjax,
            'store': ebapStore,
            'smodules': ebapSameModules
        };
    for (var m in builtInModules) {
        ebapModules[m] = builtInModules[m] || function () {};
    }
    // 将模块注册进ebapBase
    /**
     * @param {any} moduleKey
     * @param {any} module
     */
    function regesiter(moduleKey,module) {
        if (moduleKey && nativeToString.call(moduleKey) == '[object Object]') {
            $.each(moduleKey, function(m, ms) {
                if (m && ms) {
                    ebapModules[m] =  ms;
                }
            })
        } else {
            var __moduleKey = moduleKey;
            if (__moduleKey && ($.inArray(typeof module, ['function', 'object'])>-1) ) {
                ebapModules[__moduleKey] = module;
            }

        }
    }
    // 获取模块实例
    function get(options) {
        if (options.beforeParse && typeof options.beforeParse === 'function') {
            options.beforeParse();
            miniSupport('parse')();
            isParsed = true;
        } else {
            if (!isParsed) {
                miniSupport('parse')();
                isParsed = true;
            }
        }
        var __moduleKey = options.key || '';
        var __moduleArr = [];
        var optionsTimesamp = null;
        var moduleLen = null;
        var moduleDeps = {};
        var moduleSettings = {
            settings: {}
        };
        var isMounted = false;
        var returnModuleIns = null;
        // 将公共内部配置,get方法传入的配置,以及默认配置,混合后生成的配置
        options = $.extend({}, commonCfg[__moduleKey] || {}, options);
        var parseOBK = getAllOptions(options);
        var winMoudleName = '';
        var originModuleSettings = parseOBK('settings', {});
        // 获取当前所用的ui库
        config.uiLib =  parseOBK('uiLib', config.uiLib);
        // 解析options.settings
        $.each(originModuleSettings || {}, function(m, ms) {
            if (m.toLowerCase().slice(-3) === 'url') {
                moduleSettings.settings[m] = utils.prefixPath(ms);
            } else {
                moduleSettings.settings[m+'Url'] = utils.prefixPath(ms);
            }
        });
        // 对mounted或者beforeCreated返回的参数作比较
        function transformObjOrEmpty(obj) {
            if(!obj) {
                isMounted = true;
                return undefined;
            }
            if (obj && nativeToString.call(obj) === '[object Object]' && (obj.$$type === config.nameSpace || obj.$$timesamp === optionsTimesamp)) {
                isMounted = true;
                return obj;
            }
            return undefined;
        }
        if (typeof __moduleKey == 'string') {
            // 依赖解析,分析options.deps
            moduleDeps = utils.genDepsIns(options.deps);
            // 生成当前options时间戳字段,用于后续判断当前配置是否被硬性更改
            optionsTimesamp = config.nameSpace + new Date().getTime();
            options = $.extend(true,options, {moduleDeps: moduleDeps,$$timesamp: optionsTimesamp});
            // 在依赖分析完成之后,即将获取模块之前,对options进行拦截,包装
            if (options.beforeCreate && typeof options.beforeCreate === 'function') {
                options = transformObjOrEmpty(options.beforeCreate(options)) || options;
            }
            // 安全地获取某个模块
            returnModuleIns = utils.safeGetModule(ebapModules, options, moduleSettings);
            // miniui组件实例解析完成,当组件实例不是miniui实例时, options.created传入的是模块实例
            if (!parseOBK('id') && returnModuleIns) {
                options['created'] && typeof options['created'] === 'function' && options['created'](returnModuleIns, moduleDeps)
            }
            // 模块实例已经生成,即将返回的时候,执行options.mounted 方法
            if (options.mounted && typeof options.mounted === 'function' && returnModuleIns) {
                returnModuleIns = $.extend({}, returnModuleIns, transformObjOrEmpty(options.mounted(returnModuleIns || {})));
                isMounted = true;
            }
            // 将模块实例直接挂载到window下面
            if (options.name) {
                winMoudleName = (config.nameSpace + options.name).toUpperCase()+'$';
                while (window[winMoudleName]) {
                    winMoudleName = winMoudleName + '$';
                }
                window[winMoudleName] = returnModuleIns;
            }
            return returnModuleIns;
        } else if (nativeToString.call(__moduleKey) === '[object Array]') {
            // 传入的optins.key是数组时
            moduleLen = __moduleKey.length;
            for (var m = 0; m < moduleLen; m++) {
                if (__moduleKey[m] && typeof __moduleKey[m] === 'string') {
                    // 依赖解析,分析options.deps
                    moduleDeps = utils.genDepsIns(options.deps);
                    // 生成当前options时间戳字段,用于后续判断当前配置是否被硬性更改
                    optionsTimesamp = config.nameSpace + new Date().getTime();
                    options = $.extend(true,options, {moduleDeps: moduleDeps, $$timesamp: optionsTimesamp});
                    // 在依赖分析完成之后,即将获取模块之前,对options进行拦截,包装
                    if (options.beforeCreate && typeof options.beforeCreate === 'function') {
                        options = options.beforeCreate(options) || options;
                    }
                    // moduleIns = utils.getModule(ebapModules, __moduleKey[m]);
                    // moduleIns && typeof moduleIns === 'function' && (waitInject['$$type'] = config.nameSpace);
                    // 安全地获取某个模块
                    returnModuleIns = utils.safeGetModule(ebapModules, options, moduleSettings);
                    ///$.extend(true, moduleIns($.extend({},options,{moduleDeps: moduleDeps})),{ setUrls: utils.setUrls, genParseOBK: utils.genParseOBK, getDepsIns: utils.getDepsIns,extend: utils.extend, getIns: utils.getIns, insId: options.id, moduleType: options.key, moduleDeps: moduleDeps }, moduleSettings);
                    // miniui组件实例解析完成,当组件实例不是miniui实例时, options.created传入的是模块实例
                    if (!parseOBK('id') && returnModuleIns) {
                        options['created'] && typeof options['created'] === 'function' && options['created'](returnModuleIns)
                    }
                    // 模块实例已经生成,即将返回的时候,执行options.mounted 方法
                    if (options.mounted && typeof options.mounted === 'function' && returnModuleIns) {
                        if (transformObjOrEmpty(options.mounted(returnModuleIns))) {
                            returnModuleIns = $.extend({}, returnModuleIns, transformObjOrEmpty(options.mounted(returnModuleIns)));
                        }
                    }
                    // 将模块实例直接挂载到window下面
                    if (options.name) {
                        winMoudleName = (config.nameSpace + options.name).toUpperCase() + '$';
                        while (window[winMoudleName]) {
                            winMoudleName = winMoudleName + '$';
                        }
                        window[winMoudleName] = returnModuleIns;
                    }
                    __moduleArr.push(returnModuleIns)
                }
            }
            return __moduleArr;
        }
    }
    function initGlobalEvent() {
        //所有ajax请求异常的统一处理函数,处理
        $(document).ajaxError(
            function (event, xhr, options, exc) {
                if (xhr.status == 'undefined') {
                    return;
                }
                // 后台返回的错误信息
                var errorJson = support('mini', 'decode')(xhr.responseText);
                if(errorJson && errorJson.ebaperror) {
                    var resJson = {
                        desc: errorJson.message,
                        detailInfo: [
                            {
                                name: errorJson.detail,
                                description: undefined
                            }
                        ]
                    }
                    var customModal = utils.get({
                        key: 'modal',
                        tplCfg: {
                            desc: resJson.desc,
                            detailInfo: resJson.detailInfo
                        },
                        selector: '.ebap-maskContainer',
                        context: document
                    });
                }
            }
        );
    }
    for (var u in utils) {
        if (!($.inArray(u, config.enableList.lock)>-1)) {
            utilsPool[u] = utils[u];
        }
    }
    // ebapBase初始化,使用了单例,保证全局唯一
    (function init() {
        if (typeof ebapLogin === 'function') {
            var ebapLoginIns = ebapLogin({
                url: '/a/login'
            });
            ebapLoginIns.out();
        }
        initGlobalEvent();
        if (!ebapInstance) {
            ebapInstance = {
                regesiter: regesiter,
                utils: utils,
                get: get,
                setUp: setUp
            };
        }
    })();
    return ebapInstance
})();
return ebapBase;
});

// 快捷方法
var ebapUtils = ebapBase.utils;
var ebapMiniSupport = ebapUtils.miniSupport;