sexta-feira, 9 de setembro de 2016

Layout no Google Chrome

Numa aplicação usando AngularJS e Bootstrap, tenho no topo o menu e no corpo da página os dados do item selecionado no menu que normalmente são botões de ação (Inserir, Editar, etc) e filtros e abaixo a lista com os itens do cadastro.

Usei o margin-top, para posicionar a barra de ações e filtros entre o menu e a lista de itens do cadastro de forma fixa (position: fixed). No firefox funciona ok, mas para minha surpresa no Google Chrome tenho fica atrás do menu.

Entre algumas soluções encontrei o margin-top específico para Google Chrome nesse link

Também existe a opção de algo como:
/* Chrome 22-28 */
@media screen and(-webkit-min-device-pixel-ratio:0) {
    .cssclass {
        margin-top: 170px;
    }
}

/* Chrome 28 and newer */
@supports (-webkit-appearance:none) {
    .cssclass {
        margin-top: 170px;
    }
}

Infelizmente não guardei o link desse para colocar os créditos aqui.

Mas por querer usar sempre o padrão não gostei muito das alternativas, tentei o padding-top mas no meu caso não encontrei um valor que ficasse bom para todos os navegadores.

O top, diferentemente do padding-top achei um valor que ficou bom para todos os navegadores mesmo ficando levemente diferente entre o Google Chrome e os outros navegadores.


sábado, 9 de julho de 2016

Gateway de pagamento on-line

Fiz um gateway de pagamento on-line com cartão de crédito para meu cliente Lexsis, produto que está em produção desde 2014.

De fácil uso via requisições HTTPS / RESTful pode ser usado por qualquer aplicação em qualquer plataforma.

Caso precisem desse recurso em suas apps ou sites só entrar em contato com a Lexsis.

Alguns clientes que estão usando:
E também hotéis e pousadas que usam via portal de reservas on-line que fiz com AngularJS e Bootstrap:

quarta-feira, 6 de abril de 2016

Erro no Jasper referente pasta temp

Estava tendo um problema que acontecia local mas não nos servers, ao rodar um report feito em JasperReports dava o erro java.lang.NoClassDefFoundError : Could not initialize class net.sf.jasperreports.engine.util.JRStyledTextParser, procurando na web encontrei algumas possíveis soluções, um link bem completo com várias possibilidades é esse: jasper reports - Could not initialize class net.sf.jasperreports.engine.util.JRStyledTextParser - Stack Overflow.

Mas em resumo, para mim a solução foi criar a pasta temp no tomcat, como o link acima comenta o JasperReports precisa criar vários arquivos temporários.

terça-feira, 23 de fevereiro de 2016

Verificação de internet ativa para carregar libs JS remotas ou locais

Normalmente libs JS fornecem um caminho CDN e é uma boa prática usá-la porque como o browser faz cache do que baixa se outra aplicação usar a mesma lib o seu carregamento será mais rápido já que esta lib já está no cache do browser.

E hoje normalmente é mais difícil ficar sem internet, mas para evitar contratempos, ainda mais se você trabalha remoto com algum deslocamento é bom verificar se a internet está ativa e pegar as libs do CDN ou local.

Segue abaixo algumas sugestões variando conforme as linguagens de programação utilizadas:

PHP:
$internetON = @fsockopen("www.google.com", 80);

JS:
Algumas libs como jQuery e Angular criam um objeto que pode ser verificado. Esta metodologia não gosto muito porque se tiver que carregar um CSS do bootstrap por exemplo irei ter que tentar carregar a lib js na tab head e depois o css, sendo que, a boa prática recomenda carregar os CSS na tag head e os JS antes do fechamento da tag body.

<script src="http://code.jquery.com/jquery-1.11.3.min.js"/>
<script>
var internetON = (window.jQuery !== undefined);
if (internetON) {
      document.write('<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" >');
} else {
      document.write('<link rel="stylesheet" type="text/css" href="css/libs/bootstrap-3.3.6-dist/css/bootstrap.min.css">');
}
</script>

JSP / JAVA:
ApplicationUtil.java
    public static boolean internetON() {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection();
            Object objData = urlConnect.getContent();
        } catch (Exception e) { 
            return false;
        }
        
        return true;
    }

JSP
<%@ page import="br.com.lexsis.improvement.ApplicationUtil" %>
<%
    boolean internetON = false;
    if (request.getLocalName().equalsIgnoreCase("localhost")) {
        internetON = ApplicationUtil.internetON();
    } else {
        internetON = true;
    }
%>
...
<% if (internetON) { %>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<% } else { %>
<link rel="stylesheet" type="text/css" href="js/libs/bootstrap-3.3.6-dist/css/bootstrap.min.css">
<% } %>

JS / JAVA / RESTfull:
Aqui seria uma mescla do JS com JSP / JAVA. Fazer o load do AngularJS e fazer uma requisição RESTful para verificar se a internet está ON, se tiver faz a carga dos demais CSS e JS.


quinta-feira, 18 de fevereiro de 2016

Problema em decode JSON de um PUT em PHP + AngularJS

Numa aplicação PHP+AngularJS estou usando RESTful e aí no POST e PUT o decode estou fazendo da seguinte forma:

$params = json_decode(file_get_contents("php://input"));

no meu ambiente local (XAMPP e PHP versão 5.6.14) funciona 100%.

Já no server da DialHost que o PHP tem a versão 5.5.30 o PUT não funciona, pois chega os dados originais e não os novos se alterar para POST e fazendo um update, o que não é o correto para RESTful, funciona.

Abri chamado com a DialHost que sugeriram usar 

parse_str(file_get_contents("php://input"), $params);

o que funcionou num exemplo de POST e PUT que criaram, mas para mim foi pior, o POST deixou de funcionar.

Olhando melhor o código vi que eu tinha duas linhas iguais com json_decode bem afastadas, deixei só uma e funcionou. Interessante que na minha máquina como comentei acima funciona 100% mas no server gerava problema com o PUT.

Fica a dica.

Vlw pessoal da DialHost pelo pronto atendimento.


terça-feira, 2 de fevereiro de 2016

Route com templateUrl dinâmico

Normalmente os atributos templatetemplateUrl que vemos nos exemplos por aí retornam uma string, mas também pode ser uma function que retorna uma string e recebe um parâmetro com todos os atributos colocados no path. Então pode-se ter o seguinte:

when('/transpextraform/:idEmpresa/:id', {
    templateUrl: function(params) { 
        return 'ag0001.php?id_empresa=' + params.idEmpresa + "&id=" + params.id;
    },
    controller: 'TranspExtraCtrl'
})

Saiba mais:

sábado, 30 de janeiro de 2016

Route + reload e ng-click com bind

Estou usando route numa aplicação AngularJS de um cliente que estou dando manutenção. Usando PHP, AngularJS e Bootstrap.
Ao clicar num link imaginei que iria chamar novamente o controller mas isso não acontece pois utiliza o cache, devido isso tive que pensar de outra forma.
Então, removi o a href e usei o ng-click chamando uma função controlando se o item clicado foi o último clicado e se for o caso fazer o reload, pois limpar o cache também não resolveu.

Rotina pronta, outra situação para contornar o ng-click não aceita muito bem bind, no html até aparece certo mas ao passar para a function vai com os {{. Então tive que usar o parâmetro adicional no html com os parâmetros e a function ler este atributo do elemento target. E um outro detalhe como tenho um img dentro de uma tag a, na function ainda tive que verificar os parâmetros no parent do target porque dependendo de onde clicasse ia a img e não a tag a, ficando assim o código;

HTML
<a id='botao' ng-click="loadOption('transpextraform', $event);" 
                 data-parametros="{{::idEmpresa}}/{{item.id}}" title='Alterar'>
<img class='img_manutencao' src='../img/bt_019.gif' alt='Alterar'> ALTERAR
</a>

JS
function getTargetEvent(event) {
    return event.target || event.srcElement;
}

app.service("appService", function($rootScope, $route, $location, $http) {
    $rootScope.opcaoCorrente = {opcao: "", parametros: ""};
    
    $rootScope.loadOption = function(opcao, $event) {
        var target = $(getTargetEvent($event));
        var parametros = target.attr("data-parametros");
        
        if (!parametros) {
            parametros = target.parent().attr("data-parametros");
        }

        if (opcao === $rootScope.opcaoCorrente.opcao 
&& parametros === $rootScope.opcaoCorrente.parametros) {
            $route.reload();
        } else {
            $rootScope.opcaoCorrente.opcao = opcao;
            $rootScope.opcaoCorrente.parametros = parametros;
            
            if (parametros) {
                $location.path("/" + opcao + "/" + parametros);
            } else {
                $location.path("/" + opcao);
            }
        }
    };
});