<commit_before>$(document).on("ready" ,function(){
     lista_no_pip();/*llamar a mi datatablet listar proyectosinverision*/
     $("#form_AddProgramacion").submit(function(event)
                  {
                      event.preventDefault();
                      $.ajax({
                          url:base_url+"index.php/programar_nopip/AddProgramacion",
                          type:$(this).attr('method'),
                          data:$(this).serialize(),
                          success:function(resp){
                           //alert(resp);
                           if (resp=='1') {
                             swal("REGISTRADO","Se regristró correctamente", "success");
                             //formReset();
                           }
                            if (resp=='2') {
                             swal("NO SE REGISTRÓ","NO se regristró ", "error");
                           }
                          $('#Table_Programar').dataTable()._fnAjaxUpdate();//para actualizar mi datatablet datatablet   funcion
                          $('#table_NoPip').dataTable()._fnAjaxUpdate();
                            // formReset();
                         }
                      });
                  });
     $("#form_AddMeta_Pi").submit(function(event)
                  {
                      event.preventDefault();
                      $.ajax({
                          url:base_url+"index.php/programar_nopip/AddMeta_PI",
                          type:$(this).attr('method'),
                          data:$(this).serialize(),
                          success:function(resp){
                           //alert(resp);
                           if (resp=='1') {
                             swal("REGISTRADO","Se regristró correctamente", "success");
                             formReset();
                           }
                            if (resp=='2') {
                             swal("NO SE REGISTRÓ","NO se regristró ", "error");
                           }
                          $('#Table_meta_pi').dataTable()._fnAjaxUpdate();//para actualizar mi datatablet datatablet   funcion

                             formReset();
                         }
                      });
                  });
     function formReset()
          {
          document.getElementById("form_AddProgramacion").reset();
          document.getElementById("form_AddMeta_Pi").reset();
          }

});
//listar proyectos de inversion en formulacion y evaluacion
 var lista_no_pip=function()
{
       var table=$("#table_NoPip").DataTable({
                     "processing": true,
                      "serverSide":false,
                     destroy:true,
                         "ajax":{
                                    "url":base_url+"index.php/programar_nopip/Get_no_pip",
                                    "method":"POST",
                                    "dataSrc":""
                                  },
                                "columns":[
                                    {"defaultContent":"#	"},
                                    {"data":"codigo_unico_pi"},
                                    {"data":"nombre_pi"},
                                    {"data":"costo_pi"},
                                    {"data":"desc_tipo_nopip"},
                                    {"data": function (data, type, dataToSet) {

                                      if (data.estado_programado !='0') //estap programado
                                      {
                                       // return '<button type="button" class="btn btn btn-success btn-xs">Programado</button>';
                                       return '
 Programado
';
                                      }
                                      if (data.estado_programado =='0') //no esta progrmado
                                      {
                                        //return '<button type="button" class="btn btn btn-danger btn-xs">No Programado</button>';
                                        return '
No Programado
';
                                      }
                                   }},
                                    {"defaultContent":"<button type='button' title='Programar' class='programar_pip btn btn-warning btn-xs' data-toggle='modal' data-target='#Ventana_Programar'></button>"}
                                ],
                               "language":idioma_espanol
                    });
        AddProgramacion("#table_NoPip",table);
        AddMeta_Pi("#table_NoPip",table);
}
//fin de proyectos de inversion en formulacion y evaluacion
//listar programación por cada proyecto
 var listar_programacion=function(id_pi)
                {
                    var table=$("#Table_Programar").DataTable({
                      "processing": true,
                      "serverSide":false,
                       destroy:true,
                         "ajax":{
                                     url:base_url+"index.php/programar_nopip/listar_programacion",
                                     type:"POST",
                                     data :{id_pi:id_pi}
                                    },
                                "columns":[
                                    {"data":"id_pi","visible": false},
                                    {"data":"cartera"},
                                    {"data":"nombre_brecha"},
                                    {"data":"año_prog"},
                                    {"data":"monto_prog"},
                                    {"data":"prioridad_prog"},
                                    {"defaultContent":"<button type='button' class='eliminar btn btn-danger btn-xs' data-toggle='modal' data-target='#'></button>"}
                                ],
                               "language":idioma_espanol
                    });
                  EliminarProgramacion("#Table_Programar",table);
                }
//fin listar programación por cada proyecto
//Eliminar programacion
var EliminarProgramacion=function(tbody,table){
                  $(tbody).on("click","button.eliminar",function(){
                        var data=table.row( $(this).parents("tr")).data();
                        var id_pi=data.id_pi;
                        var id_cartera=data.id_cartera;
                      //  console.log(data);
                         swal({
                                title: "Desea eliminar ?",
                                text: "",
                                type: "warning",
                                showCancelButton: true,
                                confirmButtonColor: "#DD6B55",
                                confirmButtonText: "Yes,Eliminar",
                                closeOnConfirm: false
                              },
                              function(){
                                    $.ajax({
                                          url:base_url+"index.php/programar_nopip/EliminarProgramacion",
                                          type:"POST",
                                          data:
                                          {id_cartera:id_cartera,id_pi:id_pi},
                                          success:function(respuesta){
                                            //alert(respuesta);
                                            swal("Se eliminó corectamente", ".", "success");
                                            $('#Table_Programar').dataTable()._fnAjaxUpdate();//para actualizar mi datatablet datatablet
                                            $('#table_NoPip').dataTable()._fnAjaxUpdate();
                                          }
                                        });
                              });
                    });
                }

//listar meta proyecto
 var listar_meta_pi=function(id_pi)
                {
                    var table=$("#Table_meta_pi").DataTable({
                      "processing": true,
                      "serverSide":false,
                      destroy:true,
                      "ajax":{
                                     url:base_url+"index.php/programar_nopip/listar_metas_pi",
                                     type:"POST",
                                     data :{id_pi:id_pi}
                                    },
                                "columns":[
                                    {"data":"id_meta_pi","visible": false},
                                    {"data":"anio"},
                                    {"data":"pia_meta_pres"},
                                    {"data":"pim_acumulado"},
                                    {"data":"certificacion_acumulado"},
                                    {"data":"compromiso_acumulado"},
                                    {"data":"devengado_acumulado"},
                                    {"data":"girado_acumulado"},
                                    {"defaultContent":"<button type='button' class='eliminar btn btn-danger btn-xs' data-toggle='modal' data-target='#'></button>"}
                                ],
                               "language":idioma_espanol
                    });
                    EliminarMetaPresupuestal("#Table_meta_pi",table);
                }
//Eliminar Meta Presupuestal
var EliminarMetaPresupuestal=function(tbody,table){
                  $(tbody).on("click","button.eliminar",function(){
                        var data=table.row( $(this).parents("tr")).data();
                        var id_meta_pi=data.id_meta_pi;
                        console.log(data);
                         swal({
                                title: "Desea eliminar ?",
                                text: "",
                                type: "warning",
                                showCancelButton: true,
                                confirmButtonColor: "#DD6B55",
                                confirmButtonText: "Yes,Eliminar",
                                closeOnConfirm: false
                              },
                              function(){
                                    $.ajax({
                                          url:base_url+"index.php/programar_nopip/EliminarMetaPI",
                                          type:"POST",
                                          data:{id_meta_pi:id_meta_pi},
                                          success:function(respuesta){
                                            //alert(respuesta);
                                            swal("Se eliminó corectamente", ".", "success");
                                            $('#Table_meta_pi').dataTable()._fnAjaxUpdate();//para actualizar mi datatablet datatablet

                                          }
                                        });
                              });
                    });
                }
//Agregar META PIP
 var  AddMeta_Pi=function(tbody,table){
                    $(tbody).on("click","button.meta_pip",function(){
                      var data=table.row( $(this).parents("tr")).data();
                       var  id_pi=data.id_pi;
                       $("#txt_codigo_unico_pi_mp").val(data.codigo_unico_pi);
                      $("#txt_id_pip_programacion_mp").val(data.id_pi);
                      $("#txt_costo_proyecto_mp").val(data.costo_pi);
                      $("#txt_nombre_proyecto_mp").val(data.nombre_pi);

                      listar_Meta();
                      listar_meta_presupuestal();
                       listar_meta_pi(id_pi);
                    });
                }

//add operacion y manteniemito
   var  AddProgramacion=function(tbody,table){
                    $(tbody).on("click","button.programar_pip",function(){
                      var data=table.row( $(this).parents("tr")).data();
                       var  id_pi=data.id_pi;
                       $("#txt_codigo_unico_pi").val(data.codigo_unico_pi);
                      $("#txt_id_pip_programacion").val(data.id_pi);
                      $("#txt_costo_proyecto").val(data.costo_pi);
                      $("#txt_nombre_proyecto").val(data.nombre_pi);
                      $("#txt_pia_nopip").val(data.ultimo_pia_meta_pres);
                      $("#txt_devengado_nopip").val(data.devengado_acumulado_total);
                      $("#txt_pim_nopip").val(data.ultimo_pim_meta_pres);
if (parseFloat(data.ultimo_pim_meta_pres)>0) {
 // alert("nuevo");
    costopi=parseFloat(data.costo_pi)-parseFloat(data.ultimo_pim_meta_pres)-parseFloat(data.devengado_acumulado_total);
                    $("#txt_saldoprogramar").val(costopi);
}
if (data.ultimo_pim_meta_pres==""|| parseFloat(data.ultimo_pim_meta_pres)=="0.00") {
 // alert("vacio");
    costopi=parseFloat(data.costo_pi)-parseFloat(data.ultimo_pia_meta_pres)-parseFloat(data.devengado_acumulado_total);
                    $("#txt_saldoprogramar").val(costopi);
}

                        listar_aniocartera();
                        listar_programacion(id_pi);

                    });
                }
                 var listar_aniocartera=function(valor){
                     html="";
                    $("#Cbx_AnioCartera").html(html);
                    event.preventDefault();
                    $.ajax({
                        "url":base_url +"index.php/programar_pip/GetAnioCartera",
                        type:"POST",
                        success:function(respuesta3){
                         //  alert(respuesta);
                         var registros = eval(respuesta3);
                            for (var i = 0; i <registros.length;i++) {
                              html +="<option  value="+registros[i]["id_cartera"]+"> "+registros[i]["anio"]+" </option>";
                            };
                            $("#Cbx_AnioCartera").html(html);
                            $('select[name=Cbx_AnioCartera]').val(valor);//PARA AGREGAR UN COMBO PSELECIONADO
                            $('select[name=Cbx_AnioCartera]').change();
                            $('.selectpicker').selectpicker('refresh');
                            listar_Brecha();//listar brecha
                        }
                    });
                }
                var listar_Brecha=function(valor){
                     html="";
                    $("#cbxBrecha").html(html);
                    event.preventDefault();
                    $.ajax({
                        "url":base_url +"index.php/MantenimientoBrecha/GetBrecha",
                        type:"POST",
                        success:function(respuesta3){
                         //  alert(respuesta);
                         var registros = eval(respuesta3);
                            for (var i = 0; i <registros.length;i++) {
                              html +="<option  value="+registros[i]["id_brecha"]+"> "+registros[i]["nombre_brecha"]+" </option>";
                            };
                            $("#cbxBrecha").html(html);
                            $('select[name=cbxBrecha]').val(valor);//PARA AGREGAR UN COMBO PSELECIONADO
                            $('select[name=cbxBrecha]').change();
                            $('.selectpicker').selectpicker('refresh');
                        }
                    });
                }
                var listar_Meta=function(valor){
                    var html="";
                    $("#cbx_Meta").html(html);
                    event.preventDefault();
                    $.ajax({
                        "url":base_url +"index.php/Meta/listar_correlativo",
                        type:"POST",
                        success:function(respuesta3){
                         //  alert(respuesta);
                         var registros = eval(respuesta3);
                            for (var i = 0; i <registros.length;i++) {
                              html +="<option  value="+registros[i]["id_correlativo_meta"]+"> "+registros[i]["cod_correlativo"]+" </option>";
                            };
                            $("#cbx_Meta").html(html);
                            $('select[name=cbx_Meta]').val(valor);//PARA AGREGAR UN COMBO PSELECIONADO
                            $('select[name=cbx_Meta]').change();
                            $('.selectpicker').selectpicker('refresh');
                        }
                    });
                }
                /*para listar nombres de las metas*/
                var listar_meta_presupuestal=function(valor){
                     var html="";
                    $("#cbx_meta_presupuestal").html(html);
                    event.preventDefault();
                    $.ajax({
                        "url":base_url +"index.php/Meta/listar_meta_presupuestal",
                        type:"POST",
                        success:function(respuesta3){
                         //  alert(respuesta);
                         var registros = eval(respuesta3);
                            for (var i = 0; i <registros.length;i++) {
                              html +="<option  value="+registros[i]["id_meta_pres"]+"> "+registros[i]["nombre_meta_pres"]+" </option>";
                            };
                            $("#cbx_meta_presupuestal").html(html);
                            $('select[name=cbx_meta_presupuestal]').val(valor);//PARA AGREGAR UN COMBO PSELECIONADO
                            $('select[name=cbx_meta_presupuestal]').change();
                            $('.selectpicker').selectpicker('refresh');
                        }
                    });
                }
/*Idioma de datatablet table-sector */
            var idioma_espanol=
                {
                    "sProcessing":     "Procesando...",
                    "sLengthMenu":     "Mostrar _MENU_ registros",
                    "sZeroRecords":    "No se encontraron resultados",
                    "sEmptyTable":     "Ningún dato disponible en esta tabla",
                    "sInfo":           "Mostrando registros del _START_ al _END_ de un total de _TOTAL_ registros",
                    "sInfoEmpty":      "Mostrando registros del 0 al 0 de un total de 0 registros",
                    "sInfoFiltered":   "(filtrado de un total de _MAX_ registros)",
                    "sInfoPostFix":    "",
                    "sSearch":         "Buscar:",
                    "sUrl":            "",
                    "sInfoThousands":  ",",
                    "sLoadingRecords": "Cargando...",
                    "oPaginate": {
                        "sFirst":    "Primero",
                        "sLast":     "Último",
                        "sNext":     "Siguiente",
                        "sPrevious": "Anterior"
                    },
                    "oAria": {
                        "sSortAscending":  ": Activar para ordenar la columna de manera ascendente",
                        "sSortDescending": ": Activar para ordenar la columna de manera descendente"
                    }
                }
<commit_msg>mostrar años programados en no pip<commit_after>$(document).on("ready" ,function(){
     lista_no_pip();/*llamar a mi datatablet listar proyectosinverision*/
     $("#form_AddProgramacion").submit(function(event)
                  {
                      event.preventDefault();
                      $.ajax({
                          url:base_url+"index.php/programar_nopip/AddProgramacion",
                          type:$(this).attr('method'),
                          data:$(this).serialize(),
                          success:function(resp){
                           //alert(resp);
                           if (resp=='1') {
                             swal("REGISTRADO","Se regristró correctamente", "success");
                             //formReset();
                           }
                            if (resp=='2') {
                             swal("NO SE REGISTRÓ","NO se regristró ", "error");
                           }
                          $('#Table_Programar').dataTable()._fnAjaxUpdate();//para actualizar mi datatablet datatablet   funcion
                          $('#table_NoPip').dataTable()._fnAjaxUpdate();
                            // formReset();
                         }
                      });
                  });
     $("#form_AddMeta_Pi").submit(function(event)
                  {
                      event.preventDefault();
                      $.ajax({
                          url:base_url+"index.php/programar_nopip/AddMeta_PI",
                          type:$(this).attr('method'),
                          data:$(this).serialize(),
                          success:function(resp){
                           //alert(resp);
                           if (resp=='1') {
                             swal("REGISTRADO","Se regristró correctamente", "success");
                             formReset();
                           }
                            if (resp=='2') {
                             swal("NO SE REGISTRÓ","NO se regristró ", "error");
                           }
                          $('#Table_meta_pi').dataTable()._fnAjaxUpdate();//para actualizar mi datatablet datatablet   funcion

                             formReset();
                         }
                      });
                  });
     function formReset()
          {
          document.getElementById("form_AddProgramacion").reset();
          document.getElementById("form_AddMeta_Pi").reset();
          }

});
//listar proyectos de inversion en formulacion y evaluacion
 var lista_no_pip=function()
{
       var table=$("#table_NoPip").DataTable({
                     "processing": true,
                      "serverSide":false,
                     destroy:true,
                         "ajax":{
                                    "url":base_url+"index.php/programar_nopip/Get_no_pip",
                                    "method":"POST",
                                    "dataSrc":""
                                  },
                                "columns":[
                                    {"defaultContent":"#	"},
                                    {"data":"codigo_unico_pi"},
                                    {"data":"nombre_pi"},
                                    {"data":"costo_pi"},
                                    {"data":"desc_tipo_nopip"},
                                    {"data": function (data, type, dataToSet) {

                                      if (data.estado_programado !='0') //estap programado
                                      {
                                       // return '<button type="button" class="btn btn btn-success btn-xs">Programado</button>';
                                        var cadena=data.anioProgramacion.split(' ');
                                       var string='';
                                       for(var i=0;i<cadena.length;i++){
                                        var item=cadena[i].split(':');
                                        string+=''+item[0]+' ';
                                       }

                                       return '
 Programado

'+string+'
';
                                      }
                                      if (data.estado_programado =='0') //no esta progrmado
                                      {
                                        //return '<button type="button" class="btn btn btn-danger btn-xs">No Programado</button>';
                                        return '
No Programado
';
                                      }
                                   }},
                                    {"defaultContent":"<button type='button' title='Programar' class='programar_pip btn btn-warning btn-xs' data-toggle='modal' data-target='#Ventana_Programar'></button>"}
                                ],
                               "language":idioma_espanol
                    });
        AddProgramacion("#table_NoPip",table);
        AddMeta_Pi("#table_NoPip",table);
}
//fin de proyectos de inversion en formulacion y evaluacion
//listar programación por cada proyecto
 var listar_programacion=function(id_pi)
                {
                    var table=$("#Table_Programar").DataTable({
                      "processing": true,
                      "serverSide":false,
                       destroy:true,
                         "ajax":{
                                     url:base_url+"index.php/programar_nopip/listar_programacion",
                                     type:"POST",
                                     data :{id_pi:id_pi}
                                    },
                                "columns":[
                                    {"data":"id_pi","visible": false},
                                    {"data":"cartera"},
                                    {"data":"nombre_brecha"},
                                    {"data":"año_prog"},
                                    {"data":"monto_prog"},
                                    {"data":"prioridad_prog"},
                                    {"defaultContent":"<button type='button' class='eliminar btn btn-danger btn-xs' data-toggle='modal' data-target='#'></button>"}
                                ],
                               "language":idioma_espanol
                    });
                  EliminarProgramacion("#Table_Programar",table);
                }
//fin listar programación por cada proyecto
//Eliminar programacion
var EliminarProgramacion=function(tbody,table){
                  $(tbody).on("click","button.eliminar",function(){
                        var data=table.row( $(this).parents("tr")).data();
                        var id_pi=data.id_pi;
                        var id_cartera=data.id_cartera;
                      //  console.log(data);
                         swal({
                                title: "Desea eliminar ?",
                                text: "",
                                type: "warning",
                                showCancelButton: true,
                                confirmButtonColor: "#DD6B55",
                                confirmButtonText: "Yes,Eliminar",
                                closeOnConfirm: false
                              },
                              function(){
                                    $.ajax({
                                          url:base_url+"index.php/programar_nopip/EliminarProgramacion",
                                          type:"POST",
                                          data:
                                          {id_cartera:id_cartera,id_pi:id_pi},
                                          success:function(respuesta){
                                            //alert(respuesta);
                                            swal("Se eliminó corectamente", ".", "success");
                                            $('#Table_Programar').dataTable()._fnAjaxUpdate();//para actualizar mi datatablet datatablet
                                            $('#table_NoPip').dataTable()._fnAjaxUpdate();
                                          }
                                        });
                              });
                    });
                }

//listar meta proyecto
 var listar_meta_pi=function(id_pi)
                {
                    var table=$("#Table_meta_pi").DataTable({
                      "processing": true,
                      "serverSide":false,
                      destroy:true,
                      "ajax":{
                                     url:base_url+"index.php/programar_nopip/listar_metas_pi",
                                     type:"POST",
                                     data :{id_pi:id_pi}
                                    },
                                "columns":[
                                    {"data":"id_meta_pi","visible": false},
                                    {"data":"anio"},
                                    {"data":"pia_meta_pres"},
                                    {"data":"pim_acumulado"},
                                    {"data":"certificacion_acumulado"},
                                    {"data":"compromiso_acumulado"},
                                    {"data":"devengado_acumulado"},
                                    {"data":"girado_acumulado"},
                                    {"defaultContent":"<button type='button' class='eliminar btn btn-danger btn-xs' data-toggle='modal' data-target='#'></button>"}
                                ],
                               "language":idioma_espanol
                    });
                    EliminarMetaPresupuestal("#Table_meta_pi",table);
                }
//Eliminar Meta Presupuestal
var EliminarMetaPresupuestal=function(tbody,table){
                  $(tbody).on("click","button.eliminar",function(){
                        var data=table.row( $(this).parents("tr")).data();
                        var id_meta_pi=data.id_meta_pi;
                        console.log(data);
                         swal({
                                title: "Desea eliminar ?",
                                text: "",
                                type: "warning",
                                showCancelButton: true,
                                confirmButtonColor: "#DD6B55",
                                confirmButtonText: "Yes,Eliminar",
                                closeOnConfirm: false
                              },
                              function(){
                                    $.ajax({
                                          url:base_url+"index.php/programar_nopip/EliminarMetaPI",
                                          type:"POST",
                                          data:{id_meta_pi:id_meta_pi},
                                          success:function(respuesta){
                                            //alert(respuesta);
                                            swal("Se eliminó corectamente", ".", "success");
                                            $('#Table_meta_pi').dataTable()._fnAjaxUpdate();//para actualizar mi datatablet datatablet

                                          }
                                        });
                              });
                    });
                }
//Agregar META PIP
 var  AddMeta_Pi=function(tbody,table){
                    $(tbody).on("click","button.meta_pip",function(){
                      var data=table.row( $(this).parents("tr")).data();
                       var  id_pi=data.id_pi;
                       $("#txt_codigo_unico_pi_mp").val(data.codigo_unico_pi);
                      $("#txt_id_pip_programacion_mp").val(data.id_pi);
                      $("#txt_costo_proyecto_mp").val(data.costo_pi);
                      $("#txt_nombre_proyecto_mp").val(data.nombre_pi);

                      listar_Meta();
                      listar_meta_presupuestal();
                       listar_meta_pi(id_pi);
                    });
                }

//add operacion y manteniemito
   var  AddProgramacion=function(tbody,table){
                    $(tbody).on("click","button.programar_pip",function(){
                      var data=table.row( $(this).parents("tr")).data();
                       var  id_pi=data.id_pi;
                       $("#txt_codigo_unico_pi").val(data.codigo_unico_pi);
                      $("#txt_id_pip_programacion").val(data.id_pi);
                      $("#txt_costo_proyecto").val(data.costo_pi);
                      $("#txt_nombre_proyecto").val(data.nombre_pi);
                      $("#txt_pia_nopip").val(data.ultimo_pia_meta_pres);
                      $("#txt_devengado_nopip").val(data.devengado_acumulado_total);
                      $("#txt_pim_nopip").val(data.ultimo_pim_meta_pres);
if (parseFloat(data.ultimo_pim_meta_pres)>0) {
 // alert("nuevo");
    costopi=parseFloat(data.costo_pi)-parseFloat(data.ultimo_pim_meta_pres)-parseFloat(data.devengado_acumulado_total);
                    $("#txt_saldoprogramar").val(costopi);
}
if (data.ultimo_pim_meta_pres==""|| parseFloat(data.ultimo_pim_meta_pres)=="0.00") {
 // alert("vacio");
    costopi=parseFloat(data.costo_pi)-parseFloat(data.ultimo_pia_meta_pres)-parseFloat(data.devengado_acumulado_total);
                    $("#txt_saldoprogramar").val(costopi);
}

                        listar_aniocartera();
                        listar_programacion(id_pi);

                    });
                }
                 var listar_aniocartera=function(valor){
                     html="";
                    $("#Cbx_AnioCartera").html(html);
                    event.preventDefault();
                    $.ajax({
                        "url":base_url +"index.php/programar_pip/GetAnioCartera",
                        type:"POST",
                        success:function(respuesta3){
                         //  alert(respuesta);
                         var registros = eval(respuesta3);
                            for (var i = 0; i <registros.length;i++) {
                              html +="<option  value="+registros[i]["id_cartera"]+"> "+registros[i]["anio"]+" </option>";
                            };
                            $("#Cbx_AnioCartera").html(html);
                            $('select[name=Cbx_AnioCartera]').val(valor);//PARA AGREGAR UN COMBO PSELECIONADO
                            $('select[name=Cbx_AnioCartera]').change();
                            $('.selectpicker').selectpicker('refresh');
                            listar_Brecha();//listar brecha
                        }
                    });
                }
                var listar_Brecha=function(valor){
                     html="";
                    $("#cbxBrecha").html(html);
                    event.preventDefault();
                    $.ajax({
                        "url":base_url +"index.php/MantenimientoBrecha/GetBrecha",
                        type:"POST",
                        success:function(respuesta3){
                         //  alert(respuesta);
                         var registros = eval(respuesta3);
                            for (var i = 0; i <registros.length;i++) {
                              html +="<option  value="+registros[i]["id_brecha"]+"> "+registros[i]["nombre_brecha"]+" </option>";
                            };
                            $("#cbxBrecha").html(html);
                            $('select[name=cbxBrecha]').val(valor);//PARA AGREGAR UN COMBO PSELECIONADO
                            $('select[name=cbxBrecha]').change();
                            $('.selectpicker').selectpicker('refresh');
                        }
                    });
                }
                var listar_Meta=function(valor){
                    var html="";
                    $("#cbx_Meta").html(html);
                    event.preventDefault();
                    $.ajax({
                        "url":base_url +"index.php/Meta/listar_correlativo",
                        type:"POST",
                        success:function(respuesta3){
                         //  alert(respuesta);
                         var registros = eval(respuesta3);
                            for (var i = 0; i <registros.length;i++) {
                              html +="<option  value="+registros[i]["id_correlativo_meta"]+"> "+registros[i]["cod_correlativo"]+" </option>";
                            };
                            $("#cbx_Meta").html(html);
                            $('select[name=cbx_Meta]').val(valor);//PARA AGREGAR UN COMBO PSELECIONADO
                            $('select[name=cbx_Meta]').change();
                            $('.selectpicker').selectpicker('refresh');
                        }
                    });
                }
                /*para listar nombres de las metas*/
                var listar_meta_presupuestal=function(valor){
                     var html="";
                    $("#cbx_meta_presupuestal").html(html);
                    event.preventDefault();
                    $.ajax({
                        "url":base_url +"index.php/Meta/listar_meta_presupuestal",
                        type:"POST",
                        success:function(respuesta3){
                         //  alert(respuesta);
                         var registros = eval(respuesta3);
                            for (var i = 0; i <registros.length;i++) {
                              html +="<option  value="+registros[i]["id_meta_pres"]+"> "+registros[i]["nombre_meta_pres"]+" </option>";
                            };
                            $("#cbx_meta_presupuestal").html(html);
                            $('select[name=cbx_meta_presupuestal]').val(valor);//PARA AGREGAR UN COMBO PSELECIONADO
                            $('select[name=cbx_meta_presupuestal]').change();
                            $('.selectpicker').selectpicker('refresh');
                        }
                    });
                }
/*Idioma de datatablet table-sector */
            var idioma_espanol=
                {
                    "sProcessing":     "Procesando...",
                    "sLengthMenu":     "Mostrar _MENU_ registros",
                    "sZeroRecords":    "No se encontraron resultados",
                    "sEmptyTable":     "Ningún dato disponible en esta tabla",
                    "sInfo":           "Mostrando registros del _START_ al _END_ de un total de _TOTAL_ registros",
                    "sInfoEmpty":      "Mostrando registros del 0 al 0 de un total de 0 registros",
                    "sInfoFiltered":   "(filtrado de un total de _MAX_ registros)",
                    "sInfoPostFix":    "",
                    "sSearch":         "Buscar:",
                    "sUrl":            "",
                    "sInfoThousands":  ",",
                    "sLoadingRecords": "Cargando...",
                    "oPaginate": {
                        "sFirst":    "Primero",
                        "sLast":     "Último",
                        "sNext":     "Siguiente",
                        "sPrevious": "Anterior"
                    },
                    "oAria": {
                        "sSortAscending":  ": Activar para ordenar la columna de manera ascendente",
                        "sSortDescending": ": Activar para ordenar la columna de manera descendente"
                    }
                }
<|endoftext|>


<commit_before>'use strict';
/*
 * Der Heldenrechner.
 *
 * Ein Tool von den Codehelden.
 */

(function(heldenrechner, $) {

    var __ = {};

    var _data = {};
    var _mandant = null;

    __.uuid = function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    };

    __.commit = function() {
        window.localStorage['heldenrechner'] = JSON.stringify(_data);
    };

    __.activate_mandant = function() {
        $('.selected_mandant').html(_mandant.name);
        $('#main_tabs').tabs('option', 'disabled', []);
        $('#main_tabs ul li a')[1].click();
    };

    heldenrechner.select_mandant = function(uuid) {
        var mandanten = _data.mandanten.length;
        for (var i = 0; i < mandanten; i++) {
            var m = _data.mandanten[i];
            if (m.uuid === uuid) {
                _mandant = m;
                __.activate_mandant();
                return;
            }
        }
        $('#main_tabs ul li a')[0].click();
        $('#main_tabs').tabs('option', 'disabled', [1, 2]);
    };

    heldenrechner.add_mandant = function(name) {
        if ((null === name) || (name.length <= 0)) {
            $('form#new_player_form input[type="text"]').attr('placeholder', 'Bitte Spielernamen eingeben!');
            return;
        }
        var p_name = name.trim();
        if (p_name.length <= 0) {
            $('form#new_player_form input[type="text"]').attr('placeholder', 'Bitte Spielernamen eingeben!').val('');
            return;
        }
        // Gibt es den Mandanten schon?
        var mandant_exists = false;
        var mandanten = _data.mandanten.length;
        if (mandanten > 0) {
            for (var i = 0; i < mandanten; i++) {
                var m = _data.mandanten[i];
                if (m.name === p_name) {
                    mandant_exists = true;
                    break;
                }
            }
        }
        if (mandant_exists) {
            $('form#new_player_form input[type="text"]').attr('placeholder', 'Spieler exisitiert bereits!').val('');
            return;
        }
        var uuid = __.uuid();
        _data.mandanten.push({ uuid: uuid, name: p_name });
        __.commit();
        __.load_mandanten();
        $('form#new_player_form input[type="text"]').attr('placeholder', 'Spieler hinzugefügt.').val('');
    };

    __.delete_mandant = function(uuid) {
        if ((_mandant !== null) && (_mandant.uuid === uuid)) {
            _mandant = null;
            $('#main_tabs ul li a')[0].click();
            $('#main_tabs').tabs('option', 'disabled', [1, 2]);
        }
        var mandanten = _data.mandanten.length;
        var mandanten_list = [];
        for (var i = 0; i < mandanten; i++) {
            var m = _data.mandanten[i];
            if (m.uuid !== uuid) {
                mandanten_list.push(m);
            }
        }
        _data.mandanten = mandanten_list;
        __.commit();
        __.load_mandanten();
    };

    heldenrechner.delete_mandant = function(uuid) {
        var player = null;
        var mandanten = _data.mandanten.length;
        for (var i = 0; i < mandanten; i++) {
            var m = _data.mandanten[i];
            if (m.uuid === uuid) {
                player = m.name;
                break;
            }
        }
        if (null === player) {
            return;
        }
        $("#confirm-dialog").dialog({
            autoOpen: true,
            modal: true,
            title: 'Spieler wirklich löschen?',
            buttons: {
    		OK: function() {
                    __.delete_mandant(uuid);
                    $(this).dialog('close');
    		},
    		Abbrechen: function() {
                    $(this).dialog('close');
    		}
            }
        }).html('Soll der Spieler ' + player + ' wirklich gelöscht werden?

Alle seine Einstellungen und Inventories gehen verloren!');
    };

    __.rename_mandant = function(player, new_name) {
        if ((new_name === null) || (new_name.length <= 0)) {
            return;
        }
        var f_name = new_name.trim();
        if (f_name.length <= 0) {
            return;
        }
        player.name = f_name;
        __.commit();
        __.load_mandanten();
        if ((_mandant !== null) && (player.uuid === _mandant.uuid)) {
            $('.selected_mandant').html(_mandant.name);
        }
    };

    heldenrechner.rename_mandant = function(uuid) {
        var player = null;
        var mandanten = _data.mandanten.length;
        for (var i = 0; i < mandanten; i++) {
            var m = _data.mandanten[i];
            if (m.uuid === uuid) {
                player = m;
                break;
            }
        }
        if (null === player) {
            return;
        }
        var old_name = player.name;
        $('#player-rename-dialog input[type="text"]').val(old_name);
        $('#player-rename-dialog input[type="text"]').select();
        $("#player-rename-dialog").dialog({
            autoOpen: true,
            modal: true,
            title: 'Spieler umbenennen',
            buttons: {
    		OK: function() {
                    __.rename_mandant(player, $('#player-rename-dialog input[type="text"]').val());
                    $(this).dialog('close');
    		},
    		Abbrechen: function() {
                    $(this).dialog('close');
    		}
            }
        });
    };

    __.generate_mandant_actions = function(uuid) {
        var action_td = $('	');
        var select_button = $('<button>auswählen</button>').button().on('click', function() {
            heldenrechner.select_mandant(uuid);
        });
        var rename_button = $('<button>umbennenen</button>').button().on('click', function() {
            heldenrechner.rename_mandant(uuid);
        });
        var delete_button = $('<button>löschen</button>').button().on('click', function() {
            heldenrechner.delete_mandant(uuid);
        });
        $(action_td).append(select_button);
        $(action_td).append(rename_button);
        $(action_td).append(delete_button);
        return action_td;
    };

    __.load_mandanten = function() {
        if (!(_data.mandanten)) {
            _data.mandanten = [];
            __.commit();
        }
        var tbody = $('div#tab_mandanten table tbody');
        $(tbody).html('');
        var mandanten = _data.mandanten.length;
        if (mandanten > 0) {
            for (var i = 0; i < mandanten; i++) {
                var m = _data.mandanten[i];
                var tr = $('

');
                var uuid = m.uuid;
                var name_td = $('	');
                $(name_td).html(m.name);
                $(tr).append(name_td);
                $(tr).append(__.generate_mandant_actions(uuid));
                $(tbody).append(tr);
            }
        }
    };

    __.prepare_forms = function() {
        $('form#new_player_form').on('submit', function(event) {
            event.preventDefault();
            heldenrechner.add_mandant($('#new_player_name', this).val());
            return false;
        });
        $('form#new_player_form input[type="submit"]').button();
        $('#player-rename-dialog form').on('submit', function(event) {
            event.preventDefault();
            $(this).parent().parent().find('button')[1].click();
            return false;
        });
    };

    __.show_local_storage = function() {
        $('a[href="#show-local-storage"]').on('click', function() {
            var pre = $('

');
            var str = JSON.stringify(window.localStorage['heldenrechner'], null, '\t');
            $(pre).html(str);
            $('#show-local-storage').html('');
            $('#show-local-storage').append(pre);
            $('#show-local-storage').dialog({
                modal: true,
                buttons: {},
                closeOnEscape: true,
                autoOpen: true,
                title: 'Inhalt des lokalen Speichers'
            });
        });
    };

    __.loader = function() {
        $('#script_loader').dialog({
            modal: true,
            buttons: {},
            closeOnEscape: false,
            autoOpen: true,
            title: 'Anwendung wird geladen'
        }).html('Bitte warten, die Anwendung wird geladen...');
        $('#script_loader').parent().find('button').css('display', 'none');
        $('#main_tabs').css('display', 'block');
        $('#main_tabs').tabs({
            active: 0,
            disabled: [1, 2]
        });
        if (typeof(Storage) !== 'undefined') {
            if (window.localStorage['heldenrechner']) {
                _data = $.extend({}, JSON.parse(window.localStorage['heldenrechner']));
            }
            else {
                __.commit();
            }
            __.show_local_storage();
            __.prepare_forms();
            __.load_mandanten();
            $('#script_loader').dialog('close');
        }
        else {
            $('#script_loader').html('Ihr Browser stinkt. Sorry.');
        }
    };

    __.__init__ = function() {
        $('#script_loader').css('display', 'none');
        __.loader();
    };

    $(document).ready(function() {
        __.__init__();
    });

})(window.heldenrechner = window.heldenrechner || {}, jQuery);<commit_msg>Tippfehler!<commit_after>'use strict';
/*
 * Der Heldenrechner.
 *
 * Ein Tool von den Codehelden.
 */

(function(heldenrechner, $) {

    var __ = {};

    var _data = {};
    var _mandant = null;

    __.uuid = function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    };

    __.commit = function() {
        window.localStorage['heldenrechner'] = JSON.stringify(_data);
    };

    __.activate_mandant = function() {
        $('.selected_mandant').html(_mandant.name);
        $('#main_tabs').tabs('option', 'disabled', []);
        $('#main_tabs ul li a')[1].click();
    };

    heldenrechner.select_mandant = function(uuid) {
        var mandanten = _data.mandanten.length;
        for (var i = 0; i < mandanten; i++) {
            var m = _data.mandanten[i];
            if (m.uuid === uuid) {
                _mandant = m;
                __.activate_mandant();
                return;
            }
        }
        $('#main_tabs ul li a')[0].click();
        $('#main_tabs').tabs('option', 'disabled', [1, 2]);
    };

    heldenrechner.add_mandant = function(name) {
        if ((null === name) || (name.length <= 0)) {
            $('form#new_player_form input[type="text"]').attr('placeholder', 'Bitte Spielernamen eingeben!');
            return;
        }
        var p_name = name.trim();
        if (p_name.length <= 0) {
            $('form#new_player_form input[type="text"]').attr('placeholder', 'Bitte Spielernamen eingeben!').val('');
            return;
        }
        // Gibt es den Mandanten schon?
        var mandant_exists = false;
        var mandanten = _data.mandanten.length;
        if (mandanten > 0) {
            for (var i = 0; i < mandanten; i++) {
                var m = _data.mandanten[i];
                if (m.name === p_name) {
                    mandant_exists = true;
                    break;
                }
            }
        }
        if (mandant_exists) {
            $('form#new_player_form input[type="text"]').attr('placeholder', 'Spieler exisitiert bereits!').val('');
            return;
        }
        var uuid = __.uuid();
        _data.mandanten.push({ uuid: uuid, name: p_name });
        __.commit();
        __.load_mandanten();
        $('form#new_player_form input[type="text"]').attr('placeholder', 'Spieler hinzugefügt.').val('');
    };

    __.delete_mandant = function(uuid) {
        if ((_mandant !== null) && (_mandant.uuid === uuid)) {
            _mandant = null;
            $('#main_tabs ul li a')[0].click();
            $('#main_tabs').tabs('option', 'disabled', [1, 2]);
        }
        var mandanten = _data.mandanten.length;
        var mandanten_list = [];
        for (var i = 0; i < mandanten; i++) {
            var m = _data.mandanten[i];
            if (m.uuid !== uuid) {
                mandanten_list.push(m);
            }
        }
        _data.mandanten = mandanten_list;
        __.commit();
        __.load_mandanten();
    };

    heldenrechner.delete_mandant = function(uuid) {
        var player = null;
        var mandanten = _data.mandanten.length;
        for (var i = 0; i < mandanten; i++) {
            var m = _data.mandanten[i];
            if (m.uuid === uuid) {
                player = m.name;
                break;
            }
        }
        if (null === player) {
            return;
        }
        $("#confirm-dialog").dialog({
            autoOpen: true,
            modal: true,
            title: 'Spieler wirklich löschen?',
            buttons: {
    		OK: function() {
                    __.delete_mandant(uuid);
                    $(this).dialog('close');
    		},
    		Abbrechen: function() {
                    $(this).dialog('close');
    		}
            }
        }).html('Soll der Spieler ' + player + ' wirklich gelöscht werden?

Alle seine Einstellungen und Inventories gehen verloren!');
    };

    __.rename_mandant = function(player, new_name) {
        if ((new_name === null) || (new_name.length <= 0)) {
            return;
        }
        var f_name = new_name.trim();
        if (f_name.length <= 0) {
            return;
        }
        player.name = f_name;
        __.commit();
        __.load_mandanten();
        if ((_mandant !== null) && (player.uuid === _mandant.uuid)) {
            $('.selected_mandant').html(_mandant.name);
        }
    };

    heldenrechner.rename_mandant = function(uuid) {
        var player = null;
        var mandanten = _data.mandanten.length;
        for (var i = 0; i < mandanten; i++) {
            var m = _data.mandanten[i];
            if (m.uuid === uuid) {
                player = m;
                break;
            }
        }
        if (null === player) {
            return;
        }
        var old_name = player.name;
        $('#player-rename-dialog input[type="text"]').val(old_name);
        $('#player-rename-dialog input[type="text"]').select();
        $("#player-rename-dialog").dialog({
            autoOpen: true,
            modal: true,
            title: 'Spieler umbenennen',
            buttons: {
    		OK: function() {
                    __.rename_mandant(player, $('#player-rename-dialog input[type="text"]').val());
                    $(this).dialog('close');
    		},
    		Abbrechen: function() {
                    $(this).dialog('close');
    		}
            }
        });
    };

    __.generate_mandant_actions = function(uuid) {
        var action_td = $('	');
        var select_button = $('<button>auswählen</button>').button().on('click', function() {
            heldenrechner.select_mandant(uuid);
        });
        var rename_button = $('<button>umbenennen</button>').button().on('click', function() {
            heldenrechner.rename_mandant(uuid);
        });
        var delete_button = $('<button>löschen</button>').button().on('click', function() {
            heldenrechner.delete_mandant(uuid);
        });
        $(action_td).append(select_button);
        $(action_td).append(rename_button);
        $(action_td).append(delete_button);
        return action_td;
    };

    __.load_mandanten = function() {
        if (!(_data.mandanten)) {
            _data.mandanten = [];
            __.commit();
        }
        var tbody = $('div#tab_mandanten table tbody');
        $(tbody).html('');
        var mandanten = _data.mandanten.length;
        if (mandanten > 0) {
            for (var i = 0; i < mandanten; i++) {
                var m = _data.mandanten[i];
                var tr = $('

');
                var uuid = m.uuid;
                var name_td = $('	');
                $(name_td).html(m.name);
                $(tr).append(name_td);
                $(tr).append(__.generate_mandant_actions(uuid));
                $(tbody).append(tr);
            }
        }
    };

    __.prepare_forms = function() {
        $('form#new_player_form').on('submit', function(event) {
            event.preventDefault();
            heldenrechner.add_mandant($('#new_player_name', this).val());
            return false;
        });
        $('form#new_player_form input[type="submit"]').button();
        $('#player-rename-dialog form').on('submit', function(event) {
            event.preventDefault();
            $(this).parent().parent().find('button')[1].click();
            return false;
        });
    };

    __.show_local_storage = function() {
        $('a[href="#show-local-storage"]').on('click', function() {
            var pre = $('

');
            var str = JSON.stringify(window.localStorage['heldenrechner'], null, '\t');
            $(pre).html(str);
            $('#show-local-storage').html('');
            $('#show-local-storage').append(pre);
            $('#show-local-storage').dialog({
                modal: true,
                buttons: {},
                closeOnEscape: true,
                autoOpen: true,
                title: 'Inhalt des lokalen Speichers'
            });
        });
    };

    __.loader = function() {
        $('#script_loader').dialog({
            modal: true,
            buttons: {},
            closeOnEscape: false,
            autoOpen: true,
            title: 'Anwendung wird geladen'
        }).html('Bitte warten, die Anwendung wird geladen...');
        $('#script_loader').parent().find('button').css('display', 'none');
        $('#main_tabs').css('display', 'block');
        $('#main_tabs').tabs({
            active: 0,
            disabled: [1, 2]
        });
        if (typeof(Storage) !== 'undefined') {
            if (window.localStorage['heldenrechner']) {
                _data = $.extend({}, JSON.parse(window.localStorage['heldenrechner']));
            }
            else {
                __.commit();
            }
            __.show_local_storage();
            __.prepare_forms();
            __.load_mandanten();
            $('#script_loader').dialog('close');
        }
        else {
            $('#script_loader').html('Ihr Browser stinkt. Sorry.');
        }
    };

    __.__init__ = function() {
        $('#script_loader').css('display', 'none');
        __.loader();
    };

    $(document).ready(function() {
        __.__init__();
    });

})(window.heldenrechner = window.heldenrechner || {}, jQuery);<|endoftext|>


<commit_before>/* global WeatherProvider, WeatherObject, SunCalc */

/* Magic Mirror
 * Module: Weather
 * Provider: SMHI
 *
 * By BuXXi https://github.com/buxxi
 * MIT Licensed
 *
 * This class is a provider for SMHI (Sweden only).
 * Note that SMHI doesn't provide sunrise and sundown, use SunCalc to calculate it.
 * Metric system is the only supported unit.
 */
WeatherProvider.register("smhi", {
	providerName: "SMHI",

	/**
	 * Implements method in interface for fetching current weather
	 */
	fetchCurrentWeather() {
		this.fetchData(this.getURL())
			.then((data) => {
				let closest = this.getClosestToCurrentTime(data.timeSeries);
				let coordinates = this.resolveCoordinates(data);
				let weatherObject = this.convertWeatherDataToObject(closest, coordinates);
				this.setFetchedLocation(`(${coordinates.lat},${coordinates.lon})`);
				this.setCurrentWeather(weatherObject);
			})
			.catch((error) => Log.error("Could not load data: " + error.message))
			.finally(() => this.updateAvailable());
	},

	/**
	 * Implements method in interface for fetching a forecast.
	 * Handling hourly forecast would be easy as not grouping by day but it seems really specific for one weather provider for now.
	 */
	fetchWeatherForecast() {
		this.fetchData(this.getURL())
			.then((data) => {
				let coordinates = this.resolveCoordinates(data);
				let weatherObjects = this.convertWeatherDataGroupedByDay(data.timeSeries, coordinates);
				this.setFetchedLocation(`(${coordinates.lat},${coordinates.lon})`);
				this.setWeatherForecast(weatherObjects);
			})
			.catch((error) => Log.error("Could not load data: " + error.message))
			.finally(() => this.updateAvailable());
	},

	/**
	 * Overrides method for setting config with checks for the precipitationValue being unset or invalid
	 */
	setConfig(config) {
		this.config = config;
		if (!config.precipitationValue || ["pmin", "pmean", "pmedian", "pmax"].indexOf(config.precipitationValue) == -1) {
			console.log("invalid or not set: " + config.precipitationValue);
			config.precipitationValue = "pmedian";
		}
	},

	/**
	 * Of all the times returned find out which one is closest to the current time, should be the first if the data isn't old.
	 */
	getClosestToCurrentTime(times) {
		let now = moment();
		let minDiff = undefined;
		for (time of times) {
			let diff = Math.abs(moment(time.validTime).diff(now));
			if (!minDiff || diff < Math.abs(moment(minDiff.validTime).diff(now))) {
				minDiff = time;
			}
		}
		return minDiff;
	},

	/**
	 * Get the forecast url for the configured coordinates
	 */
	getURL() {
		let lon = this.config.lon;
		let lat = this.config.lat;
		return `https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/${lon}/lat/${lat}/data.json`;
	},

	/**
	 * Converts the returned data into a WeatherObject with required properties set for both current weather and forecast.
	 * The returned units is always in metric system.
	 * Requires coordinates to determine if its daytime or nighttime to know which icon to use and also to set sunrise and sunset.
	 */
	convertWeatherDataToObject(weatherData, coordinates) {
		let currentWeather = new WeatherObject("metric", "metric", "metric"); //Weather data is only for Sweden and nobody in Sweden would use imperial

		currentWeather.date = moment(weatherData.validTime);
		let times = SunCalc.getTimes(currentWeather.date.toDate(), coordinates.lat, coordinates.lon);
		currentWeather.sunrise = moment(times.sunrise, "X");
		currentWeather.sunset = moment(times.sunset, "X");
		currentWeather.humidity = this.paramValue(weatherData, "r");
		currentWeather.temperature = this.paramValue(weatherData, "t");
		currentWeather.windSpeed = this.paramValue(weatherData, "ws");
		currentWeather.windDirection = this.paramValue(weatherData, "wd");
		currentWeather.weatherType = this.convertWeatherType(this.paramValue(weatherData, "Wsymb2"), this.isDayTime(currentWeather));

		//Determine the precipitation amount and category and update the weatherObject with it, the valuetype to use can be configured or uses median as default.
		let precipitationValue = this.paramValue(weatherData, this.config.precipitationValue);
		switch (this.paramValue(weatherData, "pcat")) {
			// 0 = No precipitation
			case 1: // Snow
				currentWeather.snow += precipitationValue;
				currentWeather.precipitation += precipitationValue;
				break;
			case 2: // Snow and rain, treat it as 50/50 snow and rain
				currentWeather.snow += precipitationValue / 2;
				currentWeather.rain += precipitationValue / 2;
				currentWeather.precipitation += precipitationValue;
				break;
			case 3: // Rain
			case 4: // Drizzle
			case 5: // Freezing rain
			case 6: // Freezing drizzle
				currentWeather.rain += precipitationValue;
				currentWeather.precipitation += precipitationValue;
				break;
		}

		return currentWeather;
	},

	/**
	 * Takes all of the data points and converts it to one WeatherObject per day.
	 */
	convertWeatherDataGroupedByDay(allWeatherData, coordinates) {
		var currentWeather;
		let result = [];

		let allWeatherObjects = this.fillInGaps(allWeatherData).map((weatherData) => this.convertWeatherDataToObject(weatherData, coordinates));
		var dayWeatherTypes = [];

		for (weatherObject of allWeatherObjects) {
			//If its the first object or if a day change we need to reset the summary object
			if (!currentWeather || !currentWeather.date.isSame(weatherObject.date, "day")) {
				currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
				dayWeatherTypes = [];
				currentWeather.date = weatherObject.date;
				currentWeather.minTemperature = Infinity;
				currentWeather.maxTemperature = -Infinity;
				currentWeather.snow = 0;
				currentWeather.rain = 0;
				currentWeather.precipitation = 0;
				result.push(currentWeather);
			}

			//Keep track of what icons has been used for each hour of daytime and use the middle one for the forecast
			if (this.isDayTime(weatherObject)) {
				dayWeatherTypes.push(weatherObject.weatherType);
			}
			if (dayWeatherTypes.length > 0) {
				currentWeather.weatherType = dayWeatherTypes[Math.floor(dayWeatherTypes.length / 2)];
			} else {
				currentWeather.weatherType = weatherObject.weatherType;
			}

			//All other properties is either a sum, min or max of each hour
			currentWeather.minTemperature = Math.min(currentWeather.minTemperature, weatherObject.temperature);
			currentWeather.maxTemperature = Math.max(currentWeather.maxTemperature, weatherObject.temperature);
			currentWeather.snow += weatherObject.snow;
			currentWeather.rain += weatherObject.rain;
			currentWeather.precipitation += weatherObject.precipitation;
		}

		return result;
	},

	/**
	 * Resolve coordinates from the response data (probably preferably to use this if it's not matching the config values exactly)
	 */
	resolveCoordinates(data) {
		return { lat: data.geometry.coordinates[0][1], lon: data.geometry.coordinates[0][0] };
	},

	/**
	 * Checks if the weatherObject is at dayTime
	 */
	isDayTime(weatherObject) {
		return weatherObject.date.isBetween(weatherObject.sunrise, weatherObject.sunset, undefined, "[]");
	},

	/**
	 * The distance between the data points is increasing in the data the more distant the prediction is.
	 * Find these gaps and fill them with the previous hours data to make the data returned a complete set.
	 */
	fillInGaps(data) {
		let result = [];
		for (var i = 1; i < data.length; i++) {
			let to = moment(data[i].validTime);
			let from = moment(data[i - 1].validTime);
			let hours = moment.duration(to.diff(from)).asHours();
			// For each hour add a datapoint but change the validTime
			for (var j = 0; j < hours; j++) {
				let current = Object.assign({}, data[i]);
				current.validTime = from.clone().add(j, "hours").toISOString();
				result.push(current);
			}
		}
		return result;
	},

	/**
	 * Helper method to fetch a property from the returned data set.
	 * The returned values is an array with always one value in it.
	 */
	paramValue(currentWeatherData, name) {
		return currentWeatherData.parameters.filter((p) => p.name == name).flatMap((p) => p.values)[0];
	},

	/**
	 * Map the icon value from SHMI to an icon that MagicMirror understands.
	 * Uses different icons depending if its daytime or nighttime.
	 * SHMI's description of what the numeric value means is the comment after the case.
	 */
	convertWeatherType(input, isDayTime) {
		switch (input) {
			case 1:
				return isDayTime ? "day-sunny" : "night-clear"; // Clear sky
			case 2:
				return isDayTime ? "day-sunny-overcast" : "night-partly-cloudy"; //Nearly clear sky
			case 3:
				return isDayTime ? "day-cloudy" : "night-cloudy"; //Variable cloudiness
			case 4:
				return isDayTime ? "day-cloudy" : "night-cloudy"; //Halfclear sky
			case 5:
				return "cloudy"; //Cloudy sky
			case 6:
				return "cloudy"; //Overcast
			case 7:
				return "fog"; //Fog
			case 8:
				return "showers"; //Light rain showers
			case 9:
				return "showers"; //Moderate rain showers
			case 10:
				return "showers"; //Heavy rain showers
			case 11:
				return "thunderstorm"; //Thunderstorm
			case 12:
				return "sleet"; //Light sleet showers
			case 13:
				return "sleet"; //Moderate sleet showers
			case 14:
				return "sleet"; //Heavy sleet showers
			case 15:
				return "snow"; //Light snow showers
			case 16:
				return "snow"; //Moderate snow showers
			case 17:
				return "snow"; //Heavy snow showers
			case 18:
				return "rain"; //Light rain
			case 19:
				return "rain"; //Moderate rain
			case 20:
				return "rain"; //Heavy rain
			case 21:
				return "thunderstorm"; //Thunder
			case 22:
				return "sleet"; // Light sleet
			case 23:
				return "sleet"; //Moderate sleet
			case 24:
				return "sleet"; // Heavy sleet
			case 25:
				return "snow"; // Light snowfall
			case 26:
				return "snow"; //Moderate snowfall
			case 27:
				return "snow"; //Heavy snowfall
			default:
				return "";
		}
	}
});
<commit_msg>Stupid commit to check github actions.<commit_after>/* global WeatherProvider, WeatherObject, SunCalc */

/* Magic Mirror
 * Module: Weather
 * Provider: SMHI
 *
 * By BuXXi https://github.com/buxxi
 * MIT Licensed
 *
 * This class is a provider for SMHI (Sweden only).
 * Note that SMHI doesn't provide sunrise and sundown, use SunCalc to calculate it.
 * Metric system is the only supported unit.
 */
WeatherProvider.register("smhi", {
	providerName: "SMHI",

	/**
	 * Implements method in interface for fetching current weather
	 */
	fetchCurrentWeather() {
		this.fetchData(this.getURL())
			.then((data) => {
				let closest = this.getClosestToCurrentTime(data.timeSeries);
				let coordinates = this.resolveCoordinates(data);
				let weatherObject = this.convertWeatherDataToObject(closest, coordinates);
				this.setFetchedLocation(`(${coordinates.lat},${coordinates.lon})`);
				this.setCurrentWeather(weatherObject);
			})
			.catch((error) => Log.error("Could not load data: " + error.message))
			.finally(() => this.updateAvailable());
	},

	/**
	 * Implements method in interface for fetching a forecast.
	 * Handling hourly forecast would be easy as not grouping by day but it seems really specific for one weather provider for now.
	 */
	fetchWeatherForecast() {
		this.fetchData(this.getURL())
			.then((data) => {
				let coordinates = this.resolveCoordinates(data);
				let weatherObjects = this.convertWeatherDataGroupedByDay(data.timeSeries, coordinates);
				this.setFetchedLocation(`(${coordinates.lat},${coordinates.lon})`);
				this.setWeatherForecast(weatherObjects);
			})
			.catch((error) => Log.error("Could not load data: " + error.message))
			.finally(() => this.updateAvailable());
	},

	/**
	 * Overrides method for setting config with checks for the precipitationValue being unset or invalid
	 *
	 * @param config
	 */
	setConfig(config) {
		this.config = config;
		if (!config.precipitationValue || ["pmin", "pmean", "pmedian", "pmax"].indexOf(config.precipitationValue) == -1) {
			console.log("invalid or not set: " + config.precipitationValue);
			config.precipitationValue = "pmedian";
		}
	},

	/**
	 * Of all the times returned find out which one is closest to the current time, should be the first if the data isn't old.
	 *
	 * @param times
	 */
	getClosestToCurrentTime(times) {
		let now = moment();
		let minDiff = undefined;
		for (time of times) {
			let diff = Math.abs(moment(time.validTime).diff(now));
			if (!minDiff || diff < Math.abs(moment(minDiff.validTime).diff(now))) {
				minDiff = time;
			}
		}
		return minDiff;
	},

	/**
	 * Get the forecast url for the configured coordinates
	 */
	getURL() {
		let lon = this.config.lon;
		let lat = this.config.lat;
		return `https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/${lon}/lat/${lat}/data.json`;
	},

	/**
	 * Converts the returned data into a WeatherObject with required properties set for both current weather and forecast.
	 * The returned units is always in metric system.
	 * Requires coordinates to determine if its daytime or nighttime to know which icon to use and also to set sunrise and sunset.
	 *
	 * @param weatherData
	 * @param coordinates
	 * @param weatherData
	 * @param coordinates
	 */
	convertWeatherDataToObject(weatherData, coordinates) {
		let currentWeather = new WeatherObject("metric", "metric", "metric"); //Weather data is only for Sweden and nobody in Sweden would use imperial

		currentWeather.date = moment(weatherData.validTime);
		let times = SunCalc.getTimes(currentWeather.date.toDate(), coordinates.lat, coordinates.lon);
		currentWeather.sunrise = moment(times.sunrise, "X");
		currentWeather.sunset = moment(times.sunset, "X");
		currentWeather.humidity = this.paramValue(weatherData, "r");
		currentWeather.temperature = this.paramValue(weatherData, "t");
		currentWeather.windSpeed = this.paramValue(weatherData, "ws");
		currentWeather.windDirection = this.paramValue(weatherData, "wd");
		currentWeather.weatherType = this.convertWeatherType(this.paramValue(weatherData, "Wsymb2"), this.isDayTime(currentWeather));

		//Determine the precipitation amount and category and update the weatherObject with it, the valuetype to use can be configured or uses median as default.
		let precipitationValue = this.paramValue(weatherData, this.config.precipitationValue);
		switch (this.paramValue(weatherData, "pcat")) {
			// 0 = No precipitation
			case 1: // Snow
				currentWeather.snow += precipitationValue;
				currentWeather.precipitation += precipitationValue;
				break;
			case 2: // Snow and rain, treat it as 50/50 snow and rain
				currentWeather.snow += precipitationValue / 2;
				currentWeather.rain += precipitationValue / 2;
				currentWeather.precipitation += precipitationValue;
				break;
			case 3: // Rain
			case 4: // Drizzle
			case 5: // Freezing rain
			case 6: // Freezing drizzle
				currentWeather.rain += precipitationValue;
				currentWeather.precipitation += precipitationValue;
				break;
		}

		return currentWeather;
	},

	/**
	 * Takes all of the data points and converts it to one WeatherObject per day.
	 *
	 * @param allWeatherData
	 * @param coordinates
	 * @param allWeatherData
	 * @param coordinates
	 */
	convertWeatherDataGroupedByDay(allWeatherData, coordinates) {
		var currentWeather;
		let result = [];

		let allWeatherObjects = this.fillInGaps(allWeatherData).map((weatherData) => this.convertWeatherDataToObject(weatherData, coordinates));
		var dayWeatherTypes = [];

		for (weatherObject of allWeatherObjects) {
			//If its the first object or if a day change we need to reset the summary object
			if (!currentWeather || !currentWeather.date.isSame(weatherObject.date, "day")) {
				currentWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
				dayWeatherTypes = [];
				currentWeather.date = weatherObject.date;
				currentWeather.minTemperature = Infinity;
				currentWeather.maxTemperature = -Infinity;
				currentWeather.snow = 0;
				currentWeather.rain = 0;
				currentWeather.precipitation = 0;
				result.push(currentWeather);
			}

			//Keep track of what icons has been used for each hour of daytime and use the middle one for the forecast
			if (this.isDayTime(weatherObject)) {
				dayWeatherTypes.push(weatherObject.weatherType);
			}
			if (dayWeatherTypes.length > 0) {
				currentWeather.weatherType = dayWeatherTypes[Math.floor(dayWeatherTypes.length / 2)];
			} else {
				currentWeather.weatherType = weatherObject.weatherType;
			}

			//All other properties is either a sum, min or max of each hour
			currentWeather.minTemperature = Math.min(currentWeather.minTemperature, weatherObject.temperature);
			currentWeather.maxTemperature = Math.max(currentWeather.maxTemperature, weatherObject.temperature);
			currentWeather.snow += weatherObject.snow;
			currentWeather.rain += weatherObject.rain;
			currentWeather.precipitation += weatherObject.precipitation;
		}

		return result;
	},

	/**
	 * Resolve coordinates from the response data (probably preferably to use this if it's not matching the config values exactly)
	 *
	 * @param data
	 */
	resolveCoordinates(data) {
		return { lat: data.geometry.coordinates[0][1], lon: data.geometry.coordinates[0][0] };
	},

	/**
	 * Checks if the weatherObject is at dayTime.
	 *
	 * @param weatherObject
	 */
	isDayTime(weatherObject) {
		return weatherObject.date.isBetween(weatherObject.sunrise, weatherObject.sunset, undefined, "[]");
	},

	/**
	 * The distance between the data points is increasing in the data the more distant the prediction is.
	 * Find these gaps and fill them with the previous hours data to make the data returned a complete set.
	 *
	 * @param data
	 */
	fillInGaps(data) {
		let result = [];
		for (var i = 1; i < data.length; i++) {
			let to = moment(data[i].validTime);
			let from = moment(data[i - 1].validTime);
			let hours = moment.duration(to.diff(from)).asHours();
			// For each hour add a datapoint but change the validTime
			for (var j = 0; j < hours; j++) {
				let current = Object.assign({}, data[i]);
				current.validTime = from.clone().add(j, "hours").toISOString();
				result.push(current);
			}
		}
		return result;
	},

	/**
	 * Helper method to fetch a property from the returned data set.
	 * The returned values is an array with always one value in it.
	 *
	 * @param currentWeatherData
	 * @param name
	 * @param currentWeatherData
	 * @param name
	 */
	paramValue(currentWeatherData, name) {
		return currentWeatherData.parameters.filter((p) => p.name == name).flatMap((p) => p.values)[0];
	},

	/**
	 * Map the icon value from SHMI to an icon that MagicMirror understands.
	 * Uses different icons depending if its daytime or nighttime.
	 * SHMI's description of what the numeric value means is the comment after the case.
	 *
	 * @param input
	 * @param isDayTime
	 * @param input
	 * @param isDayTime
	 */
	convertWeatherType(input, isDayTime) {
		switch (input) {
			case 1:
				return isDayTime ? "day-sunny" : "night-clear"; // Clear sky
			case 2:
				return isDayTime ? "day-sunny-overcast" : "night-partly-cloudy"; //Nearly clear sky
			case 3:
				return isDayTime ? "day-cloudy" : "night-cloudy"; //Variable cloudiness
			case 4:
				return isDayTime ? "day-cloudy" : "night-cloudy"; //Halfclear sky
			case 5:
				return "cloudy"; //Cloudy sky
			case 6:
				return "cloudy"; //Overcast
			case 7:
				return "fog"; //Fog
			case 8:
				return "showers"; //Light rain showers
			case 9:
				return "showers"; //Moderate rain showers
			case 10:
				return "showers"; //Heavy rain showers
			case 11:
				return "thunderstorm"; //Thunderstorm
			case 12:
				return "sleet"; //Light sleet showers
			case 13:
				return "sleet"; //Moderate sleet showers
			case 14:
				return "sleet"; //Heavy sleet showers
			case 15:
				return "snow"; //Light snow showers
			case 16:
				return "snow"; //Moderate snow showers
			case 17:
				return "snow"; //Heavy snow showers
			case 18:
				return "rain"; //Light rain
			case 19:
				return "rain"; //Moderate rain
			case 20:
				return "rain"; //Heavy rain
			case 21:
				return "thunderstorm"; //Thunder
			case 22:
				return "sleet"; // Light sleet
			case 23:
				return "sleet"; //Moderate sleet
			case 24:
				return "sleet"; // Heavy sleet
			case 25:
				return "snow"; // Light snowfall
			case 26:
				return "snow"; //Moderate snowfall
			case 27:
				return "snow"; //Heavy snowfall
			default:
				return "";
		}
	}
});
<|endoftext|>


<commit_before>angular.module('ui.bootstrap.datetimepicker', ["ui.bootstrap.dateparser", "ui.bootstrap.datepicker", "ui.bootstrap.timepicker"])
  .directive('datepickerPopup', function () {
    return {
      restrict: 'EAC',
      require: 'ngModel',
      link: function (scope, element, attr, controller) {
        //remove the default formatter from the input directive to prevent conflict
        controller.$formatters.shift();
      }
    }
  })
  .directive('datetimepicker', [
    function () {
      if (angular.version.full < '1.4.0') {
        return {
          restrict: 'EA',
          template: "
Angular 1.4.0 or above is required for datetimepicker to work correctly
"
        };
      }
      return {
        restrict: 'EA',
        require: 'ngModel',
        scope: {
          ngModel: '=',
          dayFormat: "=",
          monthFormat: "=",
          yearFormat: "=",
          dayHeaderFormat: "=",
          dayTitleFormat: "=",
          monthTitleFormat: "=",
          yearRange: "=",
          minDate: "=",
          maxDate: "=",
          dateOptions: "=?",
          dateDisabled: "&",
          dateNgClick: "&",
          hourStep: "=",
          dateOpened: "=",
          minuteStep: "=",
          showMeridian: "=",
          meredians: "=",
          mousewheel: "=",
          readonlyTime: "=",
          readonlyDate: "=",
          hiddenTime: "=",
          hiddenDate: "="
        },
        template: function (elem, attrs) {
          function dashCase(name) {
            return name.replace(/[A-Z]/g, function (letter, pos) {
              return (pos ? '-' : '') + letter.toLowerCase();
            });
          }

          function createAttr(innerAttr, dateTimeAttrOpt) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + dateTimeAttr + "\" ";
            } else {
              return '';
            }
          }

          function createFuncAttr(innerAttr, funcArgs, dateTimeAttrOpt, defaultImpl) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + dateTimeAttr + "({" + funcArgs + "})\" ";
            } else {
              return angular.isDefined(defaultImpl) ? dashCase(innerAttr) + "=\"" + defaultImpl + "\"" : "";
            }
          }

          function createEvalAttr(innerAttr, dateTimeAttrOpt) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + attrs[dateTimeAttr] + "\" ";
            } else {
              return dashCase(innerAttr) + " ";
            }
          }

          function createAttrConcat(previousAttrs, attr) {
            return previousAttrs + createAttr.apply(null, attr)
          }

          var dateTmpl = "
" +
            "<input class=\"form-control\" type=\"text\" " +
            "ng-change=\"date_change($event)\" " +
            "is-open=\"innerDateOpened\" " +
            "datepicker-options=\"dateOptions\" " +
            "uib-datepicker-popup=\"{{dateFormat}}\"" +
            "ng-model=\"ngModel\" " + [
              ["dayFormat"],
              ["monthFormat"],
              ["yearFormat"],
              ["dayHeaderFormat"],
              ["dayTitleFormat"],
              ["monthTitleFormat"],
              ["yearRange"],
              ["ngHide", "hiddenDate"],
              ["ngDisabled", "readonlyDate"]
            ].reduce(createAttrConcat, '') +
            createFuncAttr("ngClick",
              "$event: $event, opened: opened",
              "dateNgClick",
              "open($event)") +
            createEvalAttr("currentText", "currentText") +
            createEvalAttr("clearText", "clearText") +
            createEvalAttr("datepickerAppendToBody", "datepickerAppendToBody") +
            createEvalAttr("closeText", "closeText") +
            createEvalAttr("placeholder", "placeholder") +
            "/>\n" +
            "
\n";
          var timeTmpl = "
\n" +
            "<uib-timepicker " + [
              ["hourStep"],
              ["minuteStep"],
              ["showMeridian"],
              ["meredians"],
              ["mousewheel"],
              ["min", "minDate"],
              ["max", "maxDate"],
              ["ngHide", "hiddenTime"],
              ["readonlyInput", "readonlyTime"]
            ].reduce(createAttrConcat, '') +
            createEvalAttr("showSpinners", "showSpinners") +
            "></timepicker>\n" +
            "
";
          var tmpl = "<ng-form name=\"datetimepickerForm\" isolate-form>" + dateTmpl + timeTmpl + "</ng-form>";
          return tmpl;
        },
        controller: ['$scope', '$attrs',
          function ($scope, $attrs) {
            $scope.createDateOptionsWatch = function(dateAttr, dateTimeAttrOpt) {
              var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : dateAttr;
              $scope.$watch(dateTimeAttr, function (value) {
                $scope.dateOptions[dateAttr] = value;
              });
            }
            $scope.date_change = function () {
              // If we changed the date only, set the time (h,m) on it.
              // This is important in case the previous date was null.
              // This solves the issue when the user set a date and time, cleared the date, and chose another date,
              // and then, the time was cleared too - which is unexpected
              var time = $scope.time;
              if ($scope.ngModel && $scope.time) { // if ngModel is null, that's because the user cleared the date field
                $scope.ngModel.setHours(time.getHours(), time.getMinutes(), 0, 0);
              }
            };

            $scope.time_change = function () {

              if ($scope.ngModel && $scope.time) {
                // convert from ISO format to Date
                if (!($scope.ngModel instanceof Date)) $scope.ngModel = new Date($scope.ngModel);
                $scope.ngModel.setHours($scope.time.getHours(), $scope.time.getMinutes(), 0, 0);
              } else {
                $scope.ngModel = new Date();
              }
            };
            $scope.open = function ($event) {
              $event.preventDefault();
              $event.stopPropagation();
              $scope.innerDateOpened = true;
            };
            $attrs.$observe('dateFormat', function(newDateFormat, oldValue) {
              $scope.dateFormat = newDateFormat;
            });
            $scope.dateOptions = angular.isDefined($scope.dateOptions) ? $scope.dateOptions : {};
            $scope.createDateOptionsWatch('minDate');
            $scope.createDateOptionsWatch('maxDate');
            $scope.dateOptions.dateDisabled = $scope.dateDisabled;
          }
        ],
        link: function (scope, element, attrs, ctrl) {
          var firstTimeAssign = true;

          scope.$watch(function () {
            return scope.ngModel;
          }, function (newTime) {
            var timeElement = document.evaluate("//*[@ng-model='time']",
              element[0], null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

            // if a time element is focused, updating its model will cause hours/minutes to be formatted by padding with leading zeros
            if (timeElement && !timeElement.contains(document.activeElement)) {

              if (newTime === null || newTime === '') { // if the newTime is not defined
                if (firstTimeAssign) { // if it's the first time we assign the time value
                  // create a new default time where the hours, minutes, seconds and milliseconds are set to 0.
                  newTime = new Date();
                  newTime.setHours(0, 0, 0, 0);
                } else { // clear the time
                  scope.time = null;
                  return;
                }
              }
              // Update timepicker (watch on ng-model in timepicker does not use object equality),
              // also if the ngModel was not a Date, convert it to date
              newTime = new Date(newTime);

              if (isNaN(newTime.getTime()) === false) {
                scope.time = newTime; // change the time in timepicker
                if (firstTimeAssign) {
                  firstTimeAssign = false;
                }
              }
            }
          }, true);

          scope.$watch(function () {
            return scope.datetimepickerForm.$error;
          }, function (errors) {
            Object.keys(ctrl.$error).forEach(function (error) {
              ctrl.$setValidity(error, true);
            });
            Object.keys(errors).forEach(function (error) {
              ctrl.$setValidity(error, false);
            });
          }, true);

          scope.$watch('dateOpened', function (value) {
            scope.innerDateOpened = value;
          });
          scope.$watch('innerDateOpened', function (value) {
            if (angular.isDefined(scope.dateOpened)) {
              scope.dateOpened = value;
            }
          });
        }
      }
    }
  ]).directive('isolateForm', [function () {
  return {
    restrict: 'A',
    require: '?form',
    link: function (scope, elm, attrs, ctrl) {
      if (!ctrl) {
        return;
      }
      // Do a copy of the controller
      var ctrlCopy = {};
      angular.copy(ctrl, ctrlCopy);

      // Get the parent of the form
      var parent = elm.parent().controller('form');
      // Remove parent link to the controller
      if (!parent) {
        return;
      }
      parent.$removeControl(ctrl);

      // Replace form controller with a "isolated form"
      var isolatedFormCtrl = {
        $setValidity: function (validationToken, isValid, control) {
          ctrlCopy.$setValidity(validationToken, isValid, control);
          parent.$setValidity(validationToken, true, ctrl);
        },
        $setDirty: function () {
          elm.removeClass('ng-pristine').addClass('ng-dirty');
          ctrl.$dirty = true;
          ctrl.$pristine = false;
        }
      };
      angular.extend(ctrl, isolatedFormCtrl);
    }
  };
}]);
<commit_msg>Adding deep watch for date options<commit_after>angular.module('ui.bootstrap.datetimepicker', ["ui.bootstrap.dateparser", "ui.bootstrap.datepicker", "ui.bootstrap.timepicker"])
  .directive('datepickerPopup', function () {
    return {
      restrict: 'EAC',
      require: 'ngModel',
      link: function (scope, element, attr, controller) {
        //remove the default formatter from the input directive to prevent conflict
        controller.$formatters.shift();
      }
    }
  })
  .directive('datetimepicker', [
    function () {
      if (angular.version.full < '1.4.0') {
        return {
          restrict: 'EA',
          template: "
Angular 1.4.0 or above is required for datetimepicker to work correctly
"
        };
      }
      return {
        restrict: 'EA',
        require: 'ngModel',
        scope: {
          ngModel: '=',
          dayFormat: "=",
          monthFormat: "=",
          yearFormat: "=",
          dayHeaderFormat: "=",
          dayTitleFormat: "=",
          monthTitleFormat: "=",
          yearRange: "=",
          minDate: "=",
          maxDate: "=",
          dateOptions: "=?",
          dateDisabled: "&",
          dateNgClick: "&",
          hourStep: "=",
          dateOpened: "=",
          minuteStep: "=",
          showMeridian: "=",
          meredians: "=",
          mousewheel: "=",
          readonlyTime: "=",
          readonlyDate: "=",
          hiddenTime: "=",
          hiddenDate: "="
        },
        template: function (elem, attrs) {
          function dashCase(name) {
            return name.replace(/[A-Z]/g, function (letter, pos) {
              return (pos ? '-' : '') + letter.toLowerCase();
            });
          }

          function createAttr(innerAttr, dateTimeAttrOpt) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + dateTimeAttr + "\" ";
            } else {
              return '';
            }
          }

          function createFuncAttr(innerAttr, funcArgs, dateTimeAttrOpt, defaultImpl) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + dateTimeAttr + "({" + funcArgs + "})\" ";
            } else {
              return angular.isDefined(defaultImpl) ? dashCase(innerAttr) + "=\"" + defaultImpl + "\"" : "";
            }
          }

          function createEvalAttr(innerAttr, dateTimeAttrOpt) {
            var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : innerAttr;
            if (attrs[dateTimeAttr]) {
              return dashCase(innerAttr) + "=\"" + attrs[dateTimeAttr] + "\" ";
            } else {
              return dashCase(innerAttr) + " ";
            }
          }

          function createAttrConcat(previousAttrs, attr) {
            return previousAttrs + createAttr.apply(null, attr)
          }

          var dateTmpl = "
" +
            "<input class=\"form-control\" type=\"text\" " +
            "ng-change=\"date_change($event)\" " +
            "is-open=\"innerDateOpened\" " +
            "datepicker-options=\"dateOptions\" " +
            "uib-datepicker-popup=\"{{dateFormat}}\"" +
            "ng-model=\"ngModel\" " + [
              ["dayFormat"],
              ["monthFormat"],
              ["yearFormat"],
              ["dayHeaderFormat"],
              ["dayTitleFormat"],
              ["monthTitleFormat"],
              ["yearRange"],
              ["ngHide", "hiddenDate"],
              ["ngDisabled", "readonlyDate"]
            ].reduce(createAttrConcat, '') +
            createFuncAttr("ngClick",
              "$event: $event, opened: opened",
              "dateNgClick",
              "open($event)") +
            createEvalAttr("currentText", "currentText") +
            createEvalAttr("clearText", "clearText") +
            createEvalAttr("datepickerAppendToBody", "datepickerAppendToBody") +
            createEvalAttr("closeText", "closeText") +
            createEvalAttr("placeholder", "placeholder") +
            "/>\n" +
            "
\n";
          var timeTmpl = "
\n" +
            "<uib-timepicker " + [
              ["hourStep"],
              ["minuteStep"],
              ["showMeridian"],
              ["meredians"],
              ["mousewheel"],
              ["min", "minDate"],
              ["max", "maxDate"],
              ["ngHide", "hiddenTime"],
              ["readonlyInput", "readonlyTime"]
            ].reduce(createAttrConcat, '') +
            createEvalAttr("showSpinners", "showSpinners") +
            "></timepicker>\n" +
            "
";
          var tmpl = "<ng-form name=\"datetimepickerForm\" isolate-form>" + dateTmpl + timeTmpl + "</ng-form>";
          return tmpl;
        },
        controller: ['$scope', '$attrs',
          function ($scope, $attrs) {
            $scope.createDateOptionsWatch = function(dateAttr, dateTimeAttrOpt) {
              var dateTimeAttr = angular.isDefined(dateTimeAttrOpt) ? dateTimeAttrOpt : dateAttr;
              $scope.$watch(dateTimeAttr, function (value) {
                $scope.dateOptions[dateAttr] = value;
              }, true);
            }
            $scope.date_change = function () {
              // If we changed the date only, set the time (h,m) on it.
              // This is important in case the previous date was null.
              // This solves the issue when the user set a date and time, cleared the date, and chose another date,
              // and then, the time was cleared too - which is unexpected
              var time = $scope.time;
              if ($scope.ngModel && $scope.time) { // if ngModel is null, that's because the user cleared the date field
                $scope.ngModel.setHours(time.getHours(), time.getMinutes(), 0, 0);
              }
            };

            $scope.time_change = function () {

              if ($scope.ngModel && $scope.time) {
                // convert from ISO format to Date
                if (!($scope.ngModel instanceof Date)) $scope.ngModel = new Date($scope.ngModel);
                $scope.ngModel.setHours($scope.time.getHours(), $scope.time.getMinutes(), 0, 0);
              } else {
                $scope.ngModel = new Date();
              }
            };
            $scope.open = function ($event) {
              $event.preventDefault();
              $event.stopPropagation();
              $scope.innerDateOpened = true;
            };
            $attrs.$observe('dateFormat', function(newDateFormat, oldValue) {
              $scope.dateFormat = newDateFormat;
            });
            $scope.dateOptions = angular.isDefined($scope.dateOptions) ? $scope.dateOptions : {};
            $scope.createDateOptionsWatch('minDate');
            $scope.createDateOptionsWatch('maxDate');
            $scope.dateOptions.dateDisabled = $scope.dateDisabled;
          }
        ],
        link: function (scope, element, attrs, ctrl) {
          var firstTimeAssign = true;

          scope.$watch(function () {
            return scope.ngModel;
          }, function (newTime) {
            var timeElement = document.evaluate("//*[@ng-model='time']",
              element[0], null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

            // if a time element is focused, updating its model will cause hours/minutes to be formatted by padding with leading zeros
            if (timeElement && !timeElement.contains(document.activeElement)) {

              if (newTime === null || newTime === '') { // if the newTime is not defined
                if (firstTimeAssign) { // if it's the first time we assign the time value
                  // create a new default time where the hours, minutes, seconds and milliseconds are set to 0.
                  newTime = new Date();
                  newTime.setHours(0, 0, 0, 0);
                } else { // clear the time
                  scope.time = null;
                  return;
                }
              }
              // Update timepicker (watch on ng-model in timepicker does not use object equality),
              // also if the ngModel was not a Date, convert it to date
              newTime = new Date(newTime);

              if (isNaN(newTime.getTime()) === false) {
                scope.time = newTime; // change the time in timepicker
                if (firstTimeAssign) {
                  firstTimeAssign = false;
                }
              }
            }
          }, true);

          scope.$watch(function () {
            return scope.datetimepickerForm.$error;
          }, function (errors) {
            Object.keys(ctrl.$error).forEach(function (error) {
              ctrl.$setValidity(error, true);
            });
            Object.keys(errors).forEach(function (error) {
              ctrl.$setValidity(error, false);
            });
          }, true);

          scope.$watch('dateOpened', function (value) {
            scope.innerDateOpened = value;
          });
          scope.$watch('innerDateOpened', function (value) {
            if (angular.isDefined(scope.dateOpened)) {
              scope.dateOpened = value;
            }
          });
        }
      }
    }
  ]).directive('isolateForm', [function () {
  return {
    restrict: 'A',
    require: '?form',
    link: function (scope, elm, attrs, ctrl) {
      if (!ctrl) {
        return;
      }
      // Do a copy of the controller
      var ctrlCopy = {};
      angular.copy(ctrl, ctrlCopy);

      // Get the parent of the form
      var parent = elm.parent().controller('form');
      // Remove parent link to the controller
      if (!parent) {
        return;
      }
      parent.$removeControl(ctrl);

      // Replace form controller with a "isolated form"
      var isolatedFormCtrl = {
        $setValidity: function (validationToken, isValid, control) {
          ctrlCopy.$setValidity(validationToken, isValid, control);
          parent.$setValidity(validationToken, true, ctrl);
        },
        $setDirty: function () {
          elm.removeClass('ng-pristine').addClass('ng-dirty');
          ctrl.$dirty = true;
          ctrl.$pristine = false;
        }
      };
      angular.extend(ctrl, isolatedFormCtrl);
    }
  };
}]);
<|endoftext|>