<commit_before>(function () {
    $(window).scroll(function () {
        var top = $(document).scrollTop();
        $('.splash').css({
            'background-position': '0px -' + (top / 3).toFixed(2) + 'px'
        });
        if (top > 50)
            $('#home > .navbar').removeClass('navbar-transparent');
        else
            $('#home > .navbar').addClass('navbar-transparent');
    });

    $("a[href='#']").click(function (e) {
        e.preventDefault();
    });

    $('.bs-component [data-toggle="popover"]').popover();
    $('.bs-component [data-toggle="tooltip"]').tooltip();

    $('#reload_actions').click(function () {
        // TODO action ajax
        $('.alert-success').show();
    });

    $(document).ready(function () {
        var vendorTable = $('#table_vendor').DataTable({
            "language": {
                url: 'datatable/locale'
            },
            "order": [[5, "desc"]],
            "processing": true,
            "serverSide": true,
            "ajax": {
                "url": "log-vendors-ajax",
                "data":
                        function (d) {
                            return $.extend({}, d, {
                                "status": $("#status-filter").val(),
                                "wallet-status": $("#wallet-status-filter").val(),
                                "date-start": $("#start").val(),
                                "date-end": $("#end").val()
                            });
                        }
            },
            "createdRow": function (row, data, index) {
                if (data.statusWalletAccount.status == 2 || data.statusWalletAccount.status == 4) {
                    $('td', row).eq(3).addClass('danger');
                } else if (data.statusWalletAccount.status == 1 || data.statusWalletAccount.status == 3) {
                    $('td', row).eq(3).addClass('success');
                }
                if (data.status.status == 3 || data.status.status == 4) {
                    $('td', row).eq(2).addClass('danger');
                } else if (data.status.status == 1 || data.status.status == 3) {
                    $('td', row).eq(2).addClass('success');
                }
            },
            "drawCallback": function () {
                $('.vendor-notice').popover();
            },
            "columns": [
                {"data": "miraklId"},
                {"data": "login"},
                {
                    "data": "status",
                    "render": function (data) {
                        return data.label + " " + data.button;

                    }
                },
                {
                    "data": "statusWalletAccount",
                    "render": function (data) {
                        return data.label;
                    }
                },
                {"data": "hipayId"},
                {"data": "date"},
                {
                    "data": "document",
                    "render": function (data) {
                        return '  Voir le detail'
                    }
                }
            ]
        });

        var operationTable = $('#table_transferts').DataTable({
            "language": {
                url: ''
            },
            "processing": true,
            "serverSide": true,
            "order": [[2, "desc"]],
            "ajax": {
                "url": "log-operations-ajax",
                "data":
                        function (d) {
                            return $.extend({}, d, {
                                "status-transfer": $("#status-transfer").val(),
                                "status-withdraw": $("#status-withdraw").val()
                            });
                        }
            },
            "createdRow": function (row, data, index) {
                if (data.statusWithDrawal.status == -7 || data.statusWithDrawal.status == -8) {
                    $('td', row).eq(5).addClass('danger');
                } else {
                    $('td', row).eq(5).addClass('success');
                }
                if (data.statusTransferts.status == -9) {
                    $('td', row).eq(4).addClass('danger');
                } else {
                    $('td', row).eq(4).addClass('success');
                }
            },
            "drawCallback": function () {
                $('.vendor-notice').popover();
            },
            "columns": [
                {"data": "miraklId"},
                {"data": "hipayId"},
                {
                    "data": "paymentVoucher",
                },
                {"data": "amount"},
                {
                    "data": "statusTransferts",
                    "render": function (data) {
                        return data.label + " " + data.button;
                    }
                },
                {
                    "data": "statusWithDrawal",
                    "render": function (data) {
                        return data.label + " " + data.button;
                    }
                },
                {
                    "data": "balance",
                }
            ]
        });
        var logTable = $('#table_logs').DataTable({
            "language": {
                url: ''
            },
            "order": [[0, "desc"]],
            "processing": true,
            "serverSide": true,
            "ajax": {
                "url": "log-general-ajax",
                "data":
                        function (d) {
                            return $.extend({}, d, {
                                "log-level": $("#log-level").val(),
                                "date-start": $("#start").val(),
                                "date-end": $("#end").val()
                            });
                        }
            },
            "columns": [
                {"data": "createdAt"},
                {"data": "levelName"},
                {"data": "action"},
                {"data": "miraklId"},
                {"data": "message"}
            ]
        });

        var batchTable = $('#table_batchs').DataTable({
            "language": {
                url: ''
            },
            "order": [[0, "desc"]],
            "processing": true,
            "serverSide": true,
            "ajax": {
                "url": "log-batch-ajax"
            },
            "drawCallback": function () {
                $('.vendor-notice').popover();
            },
            "createdRow": function (row, data, index) {
                if (data.state.state == -1) {
                    $('td', row).eq(2).addClass('danger');
                } else if (data.state.state == 1) {
                    $('td', row).eq(2).addClass('info');
                } else {
                    $('td', row).eq(2).addClass('success');
                }
            },
            "columnDefs": [{
                    "targets": 2,
                    "orderable": false
                }],
            "columns": [
                {"data": "startedAt"},
                {"data": "name"},
                {
                    "data": "state",
                    "render"
                            : function (data) {
                                return data.label + " " + data.button;
                            }
                }
            ]
        });

        $("#filter-action").click(function () {
            vendorTable.draw();
            operationTable.draw();
            logTable.draw();
        });
    });
})();

<commit_msg>Add translations<commit_after>(function () {
    $(window).scroll(function () {
        var top = $(document).scrollTop();
        $('.splash').css({
            'background-position': '0px -' + (top / 3).toFixed(2) + 'px'
        });
        if (top > 50)
            $('#home > .navbar').removeClass('navbar-transparent');
        else
            $('#home > .navbar').addClass('navbar-transparent');
    });

    $("a[href='#']").click(function (e) {
        e.preventDefault();
    });

    $('.bs-component [data-toggle="popover"]').popover();
    $('.bs-component [data-toggle="tooltip"]').tooltip();

    $('#reload_actions').click(function () {
        // TODO action ajax
        $('.alert-success').show();
    });

    $(document).ready(function () {
        var vendorTable = $('#table_vendor').DataTable({
            "language": {
                url: 'datatable/locale'
            },
            "order": [[5, "desc"]],
            "processing": true,
            "serverSide": true,
            "ajax": {
                "url": "log-vendors-ajax",
                "data":
                        function (d) {
                            return $.extend({}, d, {
                                "status": $("#status-filter").val(),
                                "wallet-status": $("#wallet-status-filter").val(),
                                "date-start": $("#start").val(),
                                "date-end": $("#end").val()
                            });
                        }
            },
            "createdRow": function (row, data, index) {
                if (data.statusWalletAccount.status == 2 || data.statusWalletAccount.status == 4) {
                    $('td', row).eq(3).addClass('danger');
                } else if (data.statusWalletAccount.status == 1 || data.statusWalletAccount.status == 3) {
                    $('td', row).eq(3).addClass('success');
                }
                if (data.status.status == 3 || data.status.status == 4) {
                    $('td', row).eq(2).addClass('danger');
                } else if (data.status.status == 1 || data.status.status == 3) {
                    $('td', row).eq(2).addClass('success');
                }
            },
            "drawCallback": function () {
                $('.vendor-notice').popover();
            },
            "columns": [
                {"data": "miraklId"},
                {"data": "login"},
                {
                    "data": "status",
                    "render": function (data) {
                        return data.label + " " + data.button;

                    }
                },
                {
                    "data": "statusWalletAccount",
                    "render": function (data) {
                        return data.label;
                    }
                },
                {"data": "hipayId"},
                {"data": "date"},
                {
                    "data": "document",
                    "render": function (data) {
                        return '  Voir le detail'
                    }
                }
            ]
        });

        var operationTable = $('#table_transferts').DataTable({
           "language": {
                url: 'datatable/locale'
            },
            "processing": true,
            "serverSide": true,
            "order": [[2, "desc"]],
            "ajax": {
                "url": "log-operations-ajax",
                "data":
                        function (d) {
                            return $.extend({}, d, {
                                "status-transfer": $("#status-transfer").val(),
                                "status-withdraw": $("#status-withdraw").val()
                            });
                        }
            },
            "createdRow": function (row, data, index) {
                if (data.statusWithDrawal.status == -7 || data.statusWithDrawal.status == -8) {
                    $('td', row).eq(5).addClass('danger');
                } else {
                    $('td', row).eq(5).addClass('success');
                }
                if (data.statusTransferts.status == -9) {
                    $('td', row).eq(4).addClass('danger');
                } else {
                    $('td', row).eq(4).addClass('success');
                }
            },
            "drawCallback": function () {
                $('.vendor-notice').popover();
            },
            "columns": [
                {"data": "miraklId"},
                {"data": "hipayId"},
                {
                    "data": "paymentVoucher",
                },
                {"data": "amount"},
                {
                    "data": "statusTransferts",
                    "render": function (data) {
                        return data.label + " " + data.button;
                    }
                },
                {
                    "data": "statusWithDrawal",
                    "render": function (data) {
                        return data.label + " " + data.button;
                    }
                },
                {
                    "data": "balance",
                }
            ]
        });
        var logTable = $('#table_logs').DataTable({
            "language": {
                url: 'datatable/locale'
            },
            "order": [[0, "desc"]],
            "processing": true,
            "serverSide": true,
            "ajax": {
                "url": "log-general-ajax",
                "data":
                        function (d) {
                            return $.extend({}, d, {
                                "log-level": $("#log-level").val(),
                                "date-start": $("#start").val(),
                                "date-end": $("#end").val()
                            });
                        }
            },
            "columns": [
                {"data": "createdAt"},
                {"data": "levelName"},
                {"data": "action"},
                {"data": "miraklId"},
                {"data": "message"}
            ]
        });

        var batchTable = $('#table_batchs').DataTable({
            "language": {
                url: 'datatable/locale'
            },
            "order": [[0, "desc"]],
            "processing": true,
            "serverSide": true,
            "ajax": {
                "url": "log-batch-ajax"
            },
            "drawCallback": function () {
                $('.vendor-notice').popover();
            },
            "createdRow": function (row, data, index) {
                if (data.state.state == -1) {
                    $('td', row).eq(2).addClass('danger');
                } else if (data.state.state == 1) {
                    $('td', row).eq(2).addClass('info');
                } else {
                    $('td', row).eq(2).addClass('success');
                }
            },
            "columnDefs": [{
                    "targets": 2,
                    "orderable": false
                }],
            "columns": [
                {"data": "startedAt"},
                {"data": "name"},
                {
                    "data": "state",
                    "render"
                            : function (data) {
                                return data.label + " " + data.button;
                            }
                }
            ]
        });

        $("#filter-action").click(function () {
            vendorTable.draw();
            operationTable.draw();
            logTable.draw();
        });
    });
})();

<|endoftext|>


<commit_before>$.showDialog=function(){
	$("#background").css('display','block');
	$("#dialog_message").css('display','block');
	$("#name_input").focus();
}

$.hideDialog=function(){
	$("#background").css('display','none');
	$("#dialog_message").css('display','none');
}

$.saveDialog=function(){
	console.log("layout.js save dailog procedure");
	var name = $("#name_input").val();
	var name_existed = 0;//if the name has existed,name_existed == 1
	$("#left li").each(function(index,ele){
		if($(ele).text()==name){
			name_existed = 1;
			return false;
		}
	});
	var new_list_id = 0;
	if(name == ""){
		$("#name_err").text("必须填写流程名称");
		$("#name_err").css('display','block');
	}
	else if(name_existed == 1){
		$("#name_err").text("流程名称'"+name+"'已存在");
		$("#name_err").css('display','block');
	}
	else{
			new_list_id = $("#lists li").length+1;
			//$("#left li:last").after("
"+name+"
");
			$("#left ul").append("
"+name+"
");

			$.hideDialog();

			$("#lists li").each(function(){
				$(this)['removeClass']('active');
			});
			$("#"+new_list_id)['addClass']('active');

			canvas.clear();
	//canvas=null;
	//canvas = new draw2d.Canvas("gfx_holder");
  canvas.installEditPolicy( new draw2d.policy.canvas.CoronaDecorationPolicy( ) );
  canvas.getCommandStack().addEventListener(function(e){
	      if(e.isPostChangeEvent()){
	      	if (e.command.label=="Connecting Ports"){
	      		if( e.command.connection.targetPort.getParent().NAME=="draw2d.shape.basic.Diamond" && e.command.connection.sourcePort.getParent().NAME=="draw2d.shape.basic.Diamond")
	      		{
	      			canvas.removeFigure(e.command.connection);
	      		}else if(e.command.connection.targetPort.getParent().NAME=="draw2d.shape.basic.Image2" && e.command.connection.sourcePort.getParent().NAME=="draw2d.shape.basic.Diamond"){
	      			//console.log("braches connect to node");
	      		}

	      	}
	          displayJSON(canvas);
	      }
	  });
	  $("#toolbar").children().remove();
	var toolbarvar=new Toolbar("toolbar",  canvas );

			$("#gfx_holder").css("display","block");
			$("#property").css("display","block");
			$("#edit_bar").css("display","block");
			$("#pro_name,#runtime,#created,#modified").val("");

			has_changed = 1;
			$.set_current_procedure(1,new_list_id);
	}
}

$.display_procedure_lists = function(){
	$.ajax({
		url:"procedure_lists.json",
		dataType:"json",
		success:function(jsonData){
			// var i = null;
			// for(i in jsonData.procedure_lists){
			// 	var list = jsonData.procedure_lists[i];
			// 	$("#left li:last").after("
"+list.name+"
");
			// }

			$.each(jsonData.procedure_lists,function(i,ele){
				//$("#left li:last").after("
"+ele.name+"
");
				$("#left ul").append("
"+ele.name+"
");
			});
		},
		error:function(jqXHR,textStatus,errorThrown){
			alert(textStatus+" "+errorThrown);
		},
	});
}

$(function(){
	$("#new").click(function(){
		var is_escape = 1;
		if(has_changed&& current_procedure['list_id']!=$(this).attr("id")){
			is_escape = confirm("内容还没有保存，确认离开吗？");
			if(is_escape){
				if(current_procedure['is_new']) $("#"+current_procedure['list_id']).remove();
			}
		}
		if(is_escape){
			$.showDialog();
			has_changed = 0;
		}

	});

	$("#background,button#cancel").live("click",function(){
		$.hideDialog();
	});

	$("button#save").on("click",function(event){
		$.saveDialog();
	});
	$("#name_input").on("keydown",function(event){
		if(event.keyCode==13){
			$.saveDialog();
		}
	});

	$.display_procedure_lists();
});
<commit_msg>comit modify 15:35<commit_after>$.showDialog=function(){
	$("#background").css('display','block');
	$("#dialog_message").css('display','block');
	$("#name_input").focus();
}

$.hideDialog=function(){
	$("#background").css('display','none');
	$("#dialog_message").css('display','none');
}

$.saveDialog=function(){
	console.log("layout.js save dailog procedure");
	var name = $("#name_input").val();
	var name_existed = 0;//if the name has existed,name_existed == 1
	$("#left li").each(function(index,ele){
		if($(ele).text()==name){
			name_existed = 1;
			return false;
		}
	});
	var new_list_id = 0;
	if(name == ""){
		$("#name_err").text("必须填写流程名称");
		$("#name_err").css('display','block');
	}
	else if(name_existed == 1){
		$("#name_err").text("流程名称'"+name+"'已存在");
		$("#name_err").css('display','block');
	}
	else{
			console.log(name);
			new_list_id = $("#lists li").length+1;
			//$("#left li:last").after("
"+name+"
");
			$("#left ul").append("
"+name+"
");
			$("#pro_name").val(name);
			$.hideDialog();

			$("#lists li").each(function(){
				$(this)['removeClass']('active');
			});
			$("#"+new_list_id)['addClass']('active');

			canvas.clear();
	//canvas=null;
	//canvas = new draw2d.Canvas("gfx_holder");
  canvas.installEditPolicy( new draw2d.policy.canvas.CoronaDecorationPolicy( ) );
  canvas.getCommandStack().addEventListener(function(e){
	      if(e.isPostChangeEvent()){
	      	if (e.command.label=="Connecting Ports"){
	      		if( e.command.connection.targetPort.getParent().NAME=="draw2d.shape.basic.Diamond" && e.command.connection.sourcePort.getParent().NAME=="draw2d.shape.basic.Diamond")
	      		{
	      			canvas.removeFigure(e.command.connection);
	      		}else if(e.command.connection.targetPort.getParent().NAME=="draw2d.shape.basic.Image2" && e.command.connection.sourcePort.getParent().NAME=="draw2d.shape.basic.Diamond"){
	      			//console.log("braches connect to node");
	      		}

	      	}
	          displayJSON(canvas);
	      }
	  });
	  $("#toolbar").children().remove();
	var toolbarvar=new Toolbar("toolbar",  canvas );

			$("#gfx_holder").css("display","block");
			$("#property").css("display","block");
			$("#edit_bar").css("display","block");
			//$("#pro_name,#runtime,#created,#modified").val("");

			has_changed = 1;
			$.set_current_procedure(1,new_list_id);
	}
}

$.display_procedure_lists = function(){
	$.ajax({
		url:"procedure_lists.json",
		dataType:"json",
		success:function(jsonData){
			// var i = null;
			// for(i in jsonData.procedure_lists){
			// 	var list = jsonData.procedure_lists[i];
			// 	$("#left li:last").after("
"+list.name+"
");
			// }

			$.each(jsonData.procedure_lists,function(i,ele){
				//$("#left li:last").after("
"+ele.name+"
");
				$("#left ul").append("
"+ele.name+"
");
			});
		},
		error:function(jqXHR,textStatus,errorThrown){
			alert(textStatus+" "+errorThrown);
		},
	});
}

$(function(){
	$("#new").click(function(){
		var is_escape = 1;
		if(has_changed&& current_procedure['list_id']!=$(this).attr("id")){
			is_escape = confirm("内容还没有保存，确认离开吗？");
			if(is_escape){
				if(current_procedure['is_new']) $("#"+current_procedure['list_id']).remove();
			}
		}
		if(is_escape){
			$.showDialog();
			has_changed = 0;
		}

	});

	$("#background,button#cancel").live("click",function(){
		$.hideDialog();
	});

	$("button#save").on("click",function(event){
		$.saveDialog();
	});
	$("#name_input").on("keydown",function(event){
		if(event.keyCode==13){
			$.saveDialog();
		}
	});

	$.display_procedure_lists();
});
<|endoftext|>


<commit_before>function submitEmail() {
    $('#step1').addClass('animated fadeOutUp');

    $.ajax( "/signup/", {type:'post', data:$( "#step1").serialize()} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#step1').removeClass('animated fadeOutUp');
        } else {
            $('#client_code').val(data.client_code);
            loadStep2();
        }
    });
}

function loadStep2() {
    $('#step1').css('display','none');
    $('#step2').css('display','block').addClass('animated fadeInUp');
}

function submitStep2() {
    $('#step2').addClass('animated fadeOutUp');

    $.ajax( "/sitecreate/", {type:'post', data:$( "#step2").serialize()} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#step2').removeClass('animated fadeOutUp');
        } else {
            process1();
        }
    });
}

function process1() {
    $('#step2').css('display','none');
    $('#step3').css('display','block').addClass('animated fadeInUp');

    $('#processBar').width('4%');

    $.ajax( "/sitecreate/0", {} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#processBar').removeClass('active');
        } else {
            $('#processBar').addClass('active');
            process2();
        }
    })
    .fail(function(){
        if($('#processBar').hasClass('active')) {
            $('#processBar').removeClass('active');
            process1();
        } else {
            displayError('Error durante el proceso.')
        }
    });
}
function process2() {
    $('#processBar').width('15%');

    $.ajax( "/sitecreate/1", {} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#processBar').removeClass('active');
        } else {
            $('#processBar').addClass('active');
            process3();
        }
    })
    .fail(function(){
        if($('#processBar').hasClass('active')) {
            $('#processBar').removeClass('active');
            process2();
        } else {
            displayError('Error durante el proceso.')
        }
    });
}
function process3() {
    $('#processBar').width('30%');

    $.ajax( "/sitecreate/2", {} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#processBar').removeClass('active');
        } else {
            $('#processBar').addClass('active');
            process4();
        }
    })
    .fail(function(){
        if($('#processBar').hasClass('active')) {
            $('#processBar').removeClass('active');
            process3();
        } else {
            displayError('Error durante el proceso.')
        }
    });
}
function process4() {
    $('#processBar').width('70%');

    $.ajax( "/sitecreate/3", {} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#processBar').removeClass('active');
        } else {
            processend();
        }
    })
    .fail(function(){
        if($('#processBar').hasClass('active')) {
            $('#processBar').removeClass('active');
            process4();
        } else {
            displayError('Error durante el proceso.')
        }
    });
}
function processend() {
    $('#processBar').width('100%');

    $('#step3').css('display','none');
    $('#step4').css('display','block');
}

function displayError(error_code) {
    $('.fa-spinner.fa-pulse').removeClass('fa-pulse');
    switch(error_code) {
        case 'empty_email': alert('Debes introducir un email'); break;
        case 'empty_fields': alert('Debes rellenar todos los campos'); break;
        case 'name_not_available': alert('Esa dirección web no está disponible. Prueba con otra.'); break;
        case 'no_client': alert('Error. No has sido registrado correctamente.'); break;
        case 'bad_request': alert('Error interno. Por favor vuelve a empezar o ponte en contacto con nosotros.'); break;
        default: alert(error_code);
    }
}<commit_msg>ProcessBar update<commit_after>function submitEmail() {
    $('#step1').addClass('animated fadeOutUp');

    $.ajax( "/signup/", {type:'post', data:$( "#step1").serialize()} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#step1').removeClass('animated fadeOutUp');
        } else {
            $('#client_code').val(data.client_code);
            loadStep2();
        }
    });
}

function loadStep2() {
    $('#step1').css('display','none');
    $('#step2').css('display','block').addClass('animated fadeInUp');
}

function submitStep2() {
    $('#step2').addClass('animated fadeOutUp');

    $.ajax( "/sitecreate/", {type:'post', data:$( "#step2").serialize()} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#step2').removeClass('animated fadeOutUp');
        } else {
            process1();
        }
    });
}

function process1() {
    $('#step2').css('display','none');
    $('#step3').css('display','block').addClass('animated fadeInUp');

    $('#processBar').width('4%');

    $.ajax( "/sitecreate/0", {} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#processBar').removeClass('active');
        } else {
            $('#processBar').addClass('active');
            process2();
        }
    })
    .fail(function(){
        if($('#processBar').hasClass('active')) {
            $('#processBar').removeClass('active');
            process1();
        } else {
            displayError('Error durante el proceso.')
        }
    });
}
function process2() {
    $('#processBar').width('15%');

    $.ajax( "/sitecreate/1", {} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#processBar').removeClass('active');
        } else {
            $('#processBar').addClass('active');
            process3();
        }
    })
    .fail(function(){
        if($('#processBar').hasClass('active')) {
            $('#processBar').removeClass('active');
            process2();
        } else {
            displayError('Error durante el proceso.')
        }
    });
}
function process3() {
    $('#processBar').width('30%');

    $.ajax( "/sitecreate/2", {} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#processBar').removeClass('active');
        } else {
            $('#processBar').addClass('active');
            process4();
        }
    })
    .fail(function(){
        if($('#processBar').hasClass('active')) {
            $('#processBar').removeClass('active');
            process3();
        } else {
            displayError('Error durante el proceso.')
        }
    });
}
function process4() {
    $('#processBar').width('80%');

    $.ajax( "/sitecreate/3", {} )
    .done(function( data ) {
        if(data.error){
            displayError(data.error);
            $('#processBar').removeClass('active');
        } else {
            processend();
        }
    })
    .fail(function(){
        if($('#processBar').hasClass('active')) {
            $('#processBar').removeClass('active');
            process4();
        } else {
            displayError('Error durante el proceso.')
        }
    });
}
function processend() {
    $('#processBar').width('100%');

    $('#step3').css('display','none');
    $('#step4').css('display','block');
}

function displayError(error_code) {
    $('.fa-spinner.fa-pulse').removeClass('fa-pulse');
    switch(error_code) {
        case 'empty_email': alert('Debes introducir un email'); break;
        case 'empty_fields': alert('Debes rellenar todos los campos'); break;
        case 'name_not_available': alert('Esa dirección web no está disponible. Prueba con otra.'); break;
        case 'no_client': alert('Error. No has sido registrado correctamente.'); break;
        case 'bad_request': alert('Error interno. Por favor vuelve a empezar o ponte en contacto con nosotros.'); break;
        default: alert(error_code);
    }
}<|endoftext|>


<commit_before>$(function() {
	$('a[data-redirect]').on('click', function(e) {
		e.preventDefault();

		$.get($(this).prop('href')).done(function(e) {
			window.location = $(this).data('redirect');
		});
	});
});<commit_msg>data-redirect="self" will now refresh the current page after GET-ing the script<commit_after>$(function() {
	$('a[data-redirect]').on('click', function(e) {
		e.preventDefault();

		var redirectUrl = $(this).data('redirect');

		$.get($(this).prop('href')).done(function(e) {
			if (redirectUrl == 'self') {
				window.location.reload();
			}
			else {
				window.location = $(this).data('redirect');
			}
		});
	});
});<|endoftext|>


<commit_before>$(function () {
	$(document).on('click', 'a[data-confirm]', function(e) {
		if (!confirm($(this).data('confirm'))) {
			$(this).data('prevented', '1');
			e.preventDefault();
		}
	});

	$(document).on('click', 'a[data-redirect]', function(e) {
		e.preventDefault();

		if ($(this).data('prevented') === '1') {
			$(this).removeData('prevented');
			return;
		}

		var redirectUrl = $(this).data('redirect');

		$(this).addClass('pleesher-loading');
		$.get($(this).prop('href')).done(function(result) {
			$(this).removeClass('pleesher-loading');
			if (redirectUrl === 'self') {
				window.location.reload();
			}
			else {
				window.location = $(this).data('redirect');
			}
		});
	});

	mw.loader.using('toastr').then(function() {
		$.getJSON(mw.util.wikiScript('api') + '?action=pleesher.check_achievements', {format: 'json'}).success(function () {
			$.getJSON(mw.util.wikiScript('api') + '?action=pleesher.notifications', {format: 'json'}).success(function (result) {
				if (!jQuery.isEmptyObject(result.notifications)) {
					var event_ids = [];
					for (var i in result.notifications) {
						var notification = result.notifications[i];
						toastr.options.timeOut = 12000;
						toastr.success(
							'' + result.notifications[i].goal.title + '',
							mw.msg('pleesher.achievement_unlocked'));
						event_ids.push(notification.id);
					}
					$.getJSON(mw.util.wikiScript('api') + '?action=pleesher.mark_notifications_read', {
						event_ids: event_ids.join('|'),
						format: 'json'
					});
				}
			});
		});
	});
});<commit_msg>jQXHR.success is deprecated and removed in jQuery 3 and superseded by jQXHR.done<commit_after>$(function () {
	$(document).on('click', 'a[data-confirm]', function(e) {
		if (!confirm($(this).data('confirm'))) {
			$(this).data('prevented', '1');
			e.preventDefault();
		}
	});

	$(document).on('click', 'a[data-redirect]', function(e) {
		e.preventDefault();

		if ($(this).data('prevented') === '1') {
			$(this).removeData('prevented');
			return;
		}

		var redirectUrl = $(this).data('redirect');

		$(this).addClass('pleesher-loading');
		$.get($(this).prop('href')).done(function(result) {
			$(this).removeClass('pleesher-loading');
			if (redirectUrl === 'self') {
				window.location.reload();
			}
			else {
				window.location = $(this).data('redirect');
			}
		});
	});

	mw.loader.using('toastr').then(function() {
		$.getJSON(mw.util.wikiScript('api') + '?action=pleesher.check_achievements', {format: 'json'}).done(function () {
			$.getJSON(mw.util.wikiScript('api') + '?action=pleesher.notifications', {format: 'json'}).done(function (result) {
				if (!jQuery.isEmptyObject(result.notifications)) {
					var event_ids = [];
					for (var i in result.notifications) {
						var notification = result.notifications[i];
						toastr.options.timeOut = 12000;
						toastr.success(
							'' + result.notifications[i].goal.title + '',
							mw.msg('pleesher.achievement_unlocked'));
						event_ids.push(notification.id);
					}
					$.getJSON(mw.util.wikiScript('api') + '?action=pleesher.mark_notifications_read', {
						event_ids: event_ids.join('|'),
						format: 'json'
					});
				}
			});
		});
	});
});<|endoftext|>


<commit_before>import Raven from 'raven-js'
import React from 'react'
import ReactDOM from 'react-dom'
import Root from 'js/root'
import { getUsername } from 'js/authentication/user'
import * as serviceWorker from 'js/serviceWorker'

// Start Sentry logger
// https://docs.sentry.io/clients/javascript/config/
const sentryDSN = process.env.REACT_APP_SENTRY_DSN
const sentryDebug = process.env.REACT_APP_SENTRY_DEBUG === 'true'
const sentryEnableAutoBreadcrumbs =
  process.env.REACT_APP_SENTRY_ENABLE_AUTO_BREADCRUMBS === 'true'
try {
  Raven.config(sentryDSN, {
    environment: process.env.REACT_APP_SENTRY_STAGE,
    debug: sentryDebug,
    // https://github.com/getsentry/raven-js/issues/723
    // https://docs.sentry.io/clients/javascript/config/
    autoBreadcrumbs: sentryEnableAutoBreadcrumbs,
    // Only log errors that originate in our JS files.
    whitelistUrls: [
      /tab\.gladly\.io\/newtab\/static/,
      /prod-tab2017\.gladly\.io\/newtab\/static/,
      /dev-tab2017\.gladly\.io\/newtab\/static/,
    ],
  }).install()
} catch (e) {
  console.error(e)
}

// Add context to Sentry logs
// https://docs.sentry.io/clients/javascript/usage/#tracking-users
try {
  const username = getUsername()
  if (username) {
    Raven.setUserContext({
      username: username,
    })
  }
} catch (e) {
  console.error(e)
}

const initApp = () => {
  require('./index.css')
  ReactDOM.render(<Root />, document.getElementById('root'))
}

try {
  Raven.context(() => {
    if (sentryDebug) {
      console.log(`Initialized Raven for Sentry DSN ${sentryDSN}`)
    }
    initApp()
  })
} catch (e) {
  console.error('Failed to wrap app in Raven.context', e)
  initApp()
}

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister()
<commit_msg>Add /search/ routes to Raven logging<commit_after>import Raven from 'raven-js'
import React from 'react'
import ReactDOM from 'react-dom'
import Root from 'js/root'
import { getUsername } from 'js/authentication/user'
import * as serviceWorker from 'js/serviceWorker'

// Start Sentry logger
// https://docs.sentry.io/clients/javascript/config/
const sentryDSN = process.env.REACT_APP_SENTRY_DSN
const sentryDebug = process.env.REACT_APP_SENTRY_DEBUG === 'true'
const sentryEnableAutoBreadcrumbs =
  process.env.REACT_APP_SENTRY_ENABLE_AUTO_BREADCRUMBS === 'true'
try {
  Raven.config(sentryDSN, {
    environment: process.env.REACT_APP_SENTRY_STAGE,
    debug: sentryDebug,
    // https://github.com/getsentry/raven-js/issues/723
    // https://docs.sentry.io/clients/javascript/config/
    autoBreadcrumbs: sentryEnableAutoBreadcrumbs,
    // Only log errors that originate in our JS files.
    whitelistUrls: [
      /tab\.gladly\.io\/newtab\/static/,
      /prod-tab2017\.gladly\.io\/newtab\/static/,
      /dev-tab2017\.gladly\.io\/newtab\/static/,
      /tab\.gladly\.io\/search\/static/,
      /prod-tab2017\.gladly\.io\/search\/static/,
      /dev-tab2017\.gladly\.io\/search\/static/,
    ],
  }).install()
} catch (e) {
  console.error(e)
}

// Add context to Sentry logs
// https://docs.sentry.io/clients/javascript/usage/#tracking-users
try {
  const username = getUsername()
  if (username) {
    Raven.setUserContext({
      username: username,
    })
  }
} catch (e) {
  console.error(e)
}

const initApp = () => {
  require('./index.css')
  ReactDOM.render(<Root />, document.getElementById('root'))
}

try {
  Raven.context(() => {
    if (sentryDebug) {
      console.log(`Initialized Raven for Sentry DSN ${sentryDSN}`)
    }
    initApp()
  })
} catch (e) {
  console.error('Failed to wrap app in Raven.context', e)
  initApp()
}

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister()
<|endoftext|>


<commit_before>/* jslint node: true, esnext: true */

'use strict';

import {
	EOFToken, StringToken, NumberToken, OperatorToken, IdentifierToken
}
from './known_tokens';

/**
 * @module pratt-parser
 */

export class Tokenizer {

	/**
	 * Creates a tokenizer for later parsing
	 * @param {object} grammar definition of the grammar with operators...
	 */
	constructor(grammar) {
		const maxOperatorLengthForFirstChar = {};
		const registeredTokens = {};

		const operatorTypes = {
			prefix: {
				nud(grammar) {
					return this.combine(grammar.expression(this.precedence));
				}
			},
			infix: {
				led(grammar, left) {
					return this.combine(left, grammar.expression(this.precedence));
				}
			},
			infixr: {
				led(grammar, left) {
					return this.combine(left, grammar.expression(this.precedence - 1));
				}
			}
		};

		function registerOperator(id, options, operatorType) {
			const props = {
				value: {
					value: id
				}
			};

			if (operatorType.led) {
				props.led = {
					value: operatorType.led,
					writable: true
				};
			}

			const op = Object.assign(Object.create(OperatorToken, props), options);

			registeredTokens[id] = op;
			return op;
		}

		for (const operatorTypeName in operatorTypes) {
			const ops = grammar[operatorTypeName];
			const operatorType = operatorTypes[operatorTypeName];

			for (const c in ops) {
				const firstChar = c[0];
				const maxLength = maxOperatorLengthForFirstChar[firstChar] || 0;

				if (maxLength < c.length) {
					maxOperatorLengthForFirstChar[firstChar] = c.length;
				}
				registerOperator(c, ops[c], operatorType);
			}
		}

		Object.defineProperty(this, 'maxOperatorLengthForFirstChar', {
			value: maxOperatorLengthForFirstChar
		});
		Object.defineProperty(this, 'registeredTokens', {
			value: registeredTokens
		});

		this._identifier = grammar.identifier || function () {};
	}

	/**
	 * @param {string} message
	 * @param {object} context token initiating the error
	 * @param {object} [values]
	 * @return {Object} error
	 */
	error(message, context, values) {
		message = `${context.lineNumber},${context.positionInLine}: ${message}`;
		if (values) message += ': ' + JSON.stringify(values);
		throw new Error(message);
	}

	makeIdentifier(value, context, contextProperties) {
		contextProperties.value = {
			value: value
		};
		this._identifier(value, contextProperties, context);
		return Object.create(IdentifierToken, contextProperties);
	}

	* tokens(chunk, context) {
		let lineNumber = 1;
		let firstCharInLine = 0;
		let i = 0;

		const getContext = () => {
			return {
				lineNumber, positionInLine: i - firstCharInLine
			};
		};

		const getContextProperties = () => {
			return {
				lineNumber: {
					value: lineNumber
				},
				positionInLine: {
					value: i - firstCharInLine
				}
			};
		};

		let c, str;
		const length = chunk.length;

		while ((c = chunk[i]) !== undefined) {
			switch (c) {
				case '_':
				case 'A':
				case 'B':
				case 'C':
				case 'D':
				case 'E':
				case 'F':
				case 'G':
				case 'H':
				case 'I':
				case 'J':
				case 'K':
				case 'L':
				case 'M':
				case 'N':
				case 'O':
				case 'P':
				case 'Q':
				case 'R':
				case 'S':
				case 'T':
				case 'U':
				case 'V':
				case 'W':
				case 'X':
				case 'Y':
				case 'Z':
				case 'a':
				case 'b':
				case 'c':
				case 'd':
				case 'e':
				case 'f':
				case 'g':
				case 'h':
				case 'i':
				case 'j':
				case 'k':
				case 'l':
				case 'm':
				case 'n':
				case 'o':
				case 'p':
				case 'q':
				case 'r':
				case 's':
				case 't':
				case 'u':
				case 'v':
				case 'w':
				case 'x':
				case 'y':
				case 'z':
					str = c;
					i += 1;
					for (;;) {
						c = chunk[i];
						if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
							(c >= '0' && c <= '9') || c === '_') {
							str += c;
							i += 1;
						} else {
							break;
						}
					}

					yield this.makeIdentifier(str, context, getContextProperties());
					break;

				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					str = c;
					i += 1;
					for (; i < length;) {
						c = chunk[i];
						if ((c < '0' || c > '9') && c !== '.' && c !== 'e' && c !== 'E') {
							break;
						}
						i += 1;
						str += c;
					}
					yield Object.create(NumberToken, Object.assign(getContextProperties(), {
						value: {
							value: +str
						}
					}));
					break;

				case '"':
				case "'":
					const tc = c;
					i += 1;
					str = '';
					for (; i < length;) {
						c = chunk[i];
						if (c === tc) {
							i += 1;
							yield Object.create(StringToken, Object.assign(getContextProperties(), {
								value: {
									value: str
								}
							}));
							break;
						} else if (c === '\\') {
							i += 1;
							c = chunk[i];
							switch (c) {
								case 'b':
									c = '\b';
									break;
								case 'f':
									c = '\f';
									break;
								case 'n':
									c = '\n';
									break;
								case 'r':
									c = '\r';
									break;
								case 't':
									c = '\t';
									break;
								case 'u':
									c = parseInt(chunk.substr(i + 1, 4), 16);
									if (!isFinite(c) || c < 0) {
										this.error('Unterminated string', getContext(), {
											value: str
										});
									}
									c = String.fromCharCode(c);
									i += 4;
									break;
							}
							str += c;
							i += 1;
						} else {
							str += c;
							i += 1;
						}
					}
					if (i === length && c !== tc) {
						this.error('Unterminated string', getContext(), {
							value: str
						});
					}
					break;

				case '\n':
					lineNumber += 1;
					firstCharInLine = i;
					i += 1;
					c = chunk[i];
					break;

				case '\b':
				case '\f':
				case '\r':
				case '\t':
				case ' ':
					i += 1;
					c = chunk[i];
					break;

				default:
					let operatorLength = this.maxOperatorLengthForFirstChar[c];
					if (operatorLength > 0) {
						do {
							const c = chunk.substring(i, i + operatorLength);
							const t = this.registeredTokens[c];
							if (t) {
								i += operatorLength;
								yield Object.create(t, getContextProperties());
								break;
							}
						} while (--operatorLength > 0);
					} else {
						i += 1;
						this.error('Unknown char', getContext(), {
							value: c
						});
					}
			}
		}
	}
}
<commit_msg>refactor: prepare for identifier token rework<commit_after>/* jslint node: true, esnext: true */

'use strict';

import {
	EOFToken, StringToken, NumberToken, OperatorToken, IdentifierToken
}
from './known_tokens';

/**
 * @module pratt-parser
 */

export class Tokenizer {

	/**
	 * Creates a tokenizer for later parsing
	 * @param {object} grammar definition of the grammar with operators...
	 */
	constructor(grammar) {
		const maxOperatorLengthForFirstChar = {};
		const registeredTokens = {};

		const operatorTypes = {
			prefix: {
				nud(grammar) {
					return this.combine(grammar.expression(this.precedence));
				}
			},
			infix: {
				led(grammar, left) {
					return this.combine(left, grammar.expression(this.precedence));
				}
			},
			infixr: {
				led(grammar, left) {
					return this.combine(left, grammar.expression(this.precedence - 1));
				}
			}
		};

		function registerOperator(id, options, operatorType) {
			const props = {
				value: {
					value: id
				}
			};

			if (operatorType.led) {
				props.led = {
					value: operatorType.led,
					writable: true
				};
			}

			const op = Object.assign(Object.create(OperatorToken, props), options);

			registeredTokens[id] = op;
			return op;
		}

		for (const operatorTypeName in operatorTypes) {
			const ops = grammar[operatorTypeName];
			const operatorType = operatorTypes[operatorTypeName];

			for (const c in ops) {
				const firstChar = c[0];
				const maxLength = maxOperatorLengthForFirstChar[firstChar] || 0;

				if (maxLength < c.length) {
					maxOperatorLengthForFirstChar[firstChar] = c.length;
				}
				registerOperator(c, ops[c], operatorType);
			}
		}

		Object.defineProperty(this, 'maxOperatorLengthForFirstChar', {
			value: maxOperatorLengthForFirstChar
		});
		Object.defineProperty(this, 'registeredTokens', {
			value: registeredTokens
		});

		this._identifier = grammar.identifier || function () {};
	}

	/**
	 * @param {string} message
	 * @param {object} context token initiating the error
	 * @param {object} [values]
	 * @return {Object} error
	 */
	error(message, context, values) {
		message = `${context.lineNumber},${context.positionInLine}: ${message}`;
		if (values) message += ': ' + JSON.stringify(values);
		throw new Error(message);
	}

	makeIdentifier(chunk, offset, context, contextProperties) {
		let i = offset;
		i += 1;
		for (;;) {
			const c = chunk[i];
			if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
				(c >= '0' && c <= '9') || c === '_') {
				i += 1;
			} else {
				break;
			}
		}

		const value = chunk.substring(offset, i);

		contextProperties.value = {
			value: value
		};
		this._identifier(value, contextProperties, context);
		return [Object.create(IdentifierToken, contextProperties), i - offset];
	}

	* tokens(chunk, context) {
		let lineNumber = 1;
		let firstCharInLine = 0;
		let i = 0;

		const getContext = () => {
			return {
				lineNumber, positionInLine: i - firstCharInLine
			};
		};

		const getContextProperties = () => {
			return {
				lineNumber: {
					value: lineNumber
				},
				positionInLine: {
					value: i - firstCharInLine
				}
			};
		};

		let c;
		const length = chunk.length;

		while ((c = chunk[i]) !== undefined) {
			switch (c) {
				case '_':
				case 'A':
				case 'B':
				case 'C':
				case 'D':
				case 'E':
				case 'F':
				case 'G':
				case 'H':
				case 'I':
				case 'J':
				case 'K':
				case 'L':
				case 'M':
				case 'N':
				case 'O':
				case 'P':
				case 'Q':
				case 'R':
				case 'S':
				case 'T':
				case 'U':
				case 'V':
				case 'W':
				case 'X':
				case 'Y':
				case 'Z':
				case 'a':
				case 'b':
				case 'c':
				case 'd':
				case 'e':
				case 'f':
				case 'g':
				case 'h':
				case 'i':
				case 'j':
				case 'k':
				case 'l':
				case 'm':
				case 'n':
				case 'o':
				case 'p':
				case 'q':
				case 'r':
				case 's':
				case 't':
				case 'u':
				case 'v':
				case 'w':
				case 'x':
				case 'y':
				case 'z':
					const [t, l] = this.makeIdentifier(chunk, i, context, getContextProperties());
					i += l;
					yield t;
					break;

				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					{
						let str = c;
						i += 1;
						for (; i < length;) {
							c = chunk[i];
							if ((c < '0' || c > '9') && c !== '.' && c !== 'e' && c !== 'E') {
								break;
							}
							i += 1;
							str += c;
						}
						yield Object.create(NumberToken, Object.assign(getContextProperties(), {
							value: {
								value: +str
							}
						}));
					}
					break;

				case '"':
				case "'":
					{
						const tc = c;
						let str = '';

						i += 1;
						for (; i < length;) {
							c = chunk[i];
							if (c === tc) {
								i += 1;
								yield Object.create(StringToken, Object.assign(getContextProperties(), {
									value: {
										value: str
									}
								}));
								break;
							} else if (c === '\\') {
								i += 1;
								c = chunk[i];
								switch (c) {
									case 'b':
										c = '\b';
										break;
									case 'f':
										c = '\f';
										break;
									case 'n':
										c = '\n';
										break;
									case 'r':
										c = '\r';
										break;
									case 't':
										c = '\t';
										break;
									case 'u':
										c = parseInt(chunk.substr(i + 1, 4), 16);
										if (!isFinite(c) || c < 0) {
											this.error('Unterminated string', getContext(), {
												value: str
											});
										}
										c = String.fromCharCode(c);
										i += 4;
										break;
								}
								str += c;
								i += 1;
							} else {
								str += c;
								i += 1;
							}
						}
						if (i === length && c !== tc) {
							this.error('Unterminated string', getContext(), {
								value: str
							});
						}
					}
					break;

				case '\n':
					lineNumber += 1;
					firstCharInLine = i;
					i += 1;
					c = chunk[i];
					break;

				case '\b':
				case '\f':
				case '\r':
				case '\t':
				case ' ':
					i += 1;
					c = chunk[i];
					break;

				default:
					let operatorLength = this.maxOperatorLengthForFirstChar[c];
					if (operatorLength > 0) {
						do {
							const c = chunk.substring(i, i + operatorLength);
							const t = this.registeredTokens[c];
							if (t) {
								i += operatorLength;
								yield Object.create(t, getContextProperties());
								break;
							}
						} while (--operatorLength > 0);
					} else {
						i += 1;
						this.error('Unknown char', getContext(), {
							value: c
						});
					}
			}
		}
	}
}
<|endoftext|>


<commit_before>var Duplex = require('./duplex');
var inherits = require('inherits');

var Transform = module.exports = function Transform (opts) {
    var stream = this,
        ts;
    Duplex.call(this, opts);
    ts = this._transformState = new TransformState(opts, this);

    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;

    this.once('finish', function () {
        if (typeof stream._flush === 'function') {
            stream._flush(function (errback) {
                stream._doneTransforming(err);
            });
        } else {
            stream._doneTransforming();
        }
    });
}

inherits(Transform, Duplex);

/**
 * Transform subclasses should implement this
 * Call `.push(data)` to pass data to the Readable side.
 * Call `errback(err)` when you are done with this chunk. If you pass an
 *     err, then it will be emitted. If you never call `errback`, then
 *     you'll never get another chunk.
 */
Transform.prototype._transform = function (chunk, errback) {
    this.emit('error', new Error('_transform not implemented!'));
};

Transform.prototype.push = function (chunk) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.apply(this, arguments);
};

/**
 * Must be implemented here because Transform is a Readable
 */
Transform.prototype._read = function () {
    var ts = this._transformState;

    if (ts.writechunk !== null && ts.writecb && ! ts.transforming) {
        ts.transforming = true;
        this._transform(ts.writechunk, ts.afterTransform);
    } else {
        // mark that we need a transform, so that any data that comes in
        // will get processed, now that it's been asked for
        ts.needTransform = true;
    }
};

/**
 * Must be implemented here because Transform is Writable
 */
Transform.prototype._write = function (chunk, errback) {
    var ts = this._transformState,
        rs = this._readableState;
    ts.writecb = errback;
    ts.writechunk = chunk;
    if ( ! ts.transforming ) {
        if (ts.needTransform ||
            rs.needReadable ||
            rs.buffer.length < rs.highWaterMark) {
            this._read(rs.highWaterMark);
        }
    }
};

Transform.prototype._afterTransform = function (err, data) {
    var ts = this._transformState,
        rs = this._readableState,
        errback = ts.writecb;

    ts.transforming = false;

    if ( ! errback) {
        return this.emit('error', new Error('no writecb in Transform class'));
    }

    ts.writechunk = null;
    ts.writecb = null;

    if (data !== null && data !== undefined) {
        this.push(data);
    }

    if (errback) {
        errback(err);
    }

    rs.reading = false;

    if (rs.needReadable || rs.buffer.length < rs.highWaterMark) {
        this._read(rs.highWaterMark);
    }
};

Transform.prototype._doneTransforming = function (err) {
    if (err) {
        this.emit('error', err);
    }

    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = this._writableState,
        ts = this._transformState;

    if (ws.buffer.length) {
        throw new Error('Calling Transform#_doneTransforming when writable buffer not empty');
    }

    if (ts.transforming) {
        throw new Error('Calling Transform#_doneTransforming when still transforming');
    }

    return this.push(null);
};

function TransformState (opts, stream) {
    this.afterTransform = function (err, data) {
        return stream._afterTransform(err, data);
    };

    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
}
<commit_msg>Transforms can push undefined without being treated like null<commit_after>var Duplex = require('./duplex');
var inherits = require('inherits');

var Transform = module.exports = function Transform (opts) {
    var stream = this,
        ts;
    Duplex.call(this, opts);
    ts = this._transformState = new TransformState(opts, this);

    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;

    this.once('finish', function () {
        if (typeof stream._flush === 'function') {
            stream._flush(function (errback) {
                stream._doneTransforming(err);
            });
        } else {
            stream._doneTransforming();
        }
    });
}

inherits(Transform, Duplex);

/**
 * Transform subclasses should implement this
 * Call `.push(data)` to pass data to the Readable side.
 * Call `errback(err)` when you are done with this chunk. If you pass an
 *     err, then it will be emitted. If you never call `errback`, then
 *     you'll never get another chunk.
 */
Transform.prototype._transform = function (chunk, errback) {
    this.emit('error', new Error('_transform not implemented!'));
};

Transform.prototype.push = function (chunk) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.apply(this, arguments);
};

/**
 * Must be implemented here because Transform is a Readable
 */
Transform.prototype._read = function () {
    var ts = this._transformState;

    if (ts.writechunk !== null && ts.writecb && ! ts.transforming) {
        ts.transforming = true;
        this._transform(ts.writechunk, ts.afterTransform);
    } else {
        // mark that we need a transform, so that any data that comes in
        // will get processed, now that it's been asked for
        ts.needTransform = true;
    }
};

/**
 * Must be implemented here because Transform is Writable
 */
Transform.prototype._write = function (chunk, errback) {
    var ts = this._transformState,
        rs = this._readableState;
    ts.writecb = errback;
    ts.writechunk = chunk;
    if ( ! ts.transforming ) {
        if (ts.needTransform ||
            rs.needReadable ||
            rs.buffer.length < rs.highWaterMark) {
            this._read(rs.highWaterMark);
        }
    }
};

Transform.prototype._afterTransform = function (err, data) {
    var ts = this._transformState,
        rs = this._readableState,
        errback = ts.writecb;

    ts.transforming = false;

    if ( ! errback) {
        return this.emit('error', new Error('no writecb in Transform class'));
    }

    ts.writechunk = null;
    ts.writecb = null;

    if (data !== null) {
        this.push(data);
    }

    if (errback) {
        errback(err);
    }

    rs.reading = false;

    if (rs.needReadable || rs.buffer.length < rs.highWaterMark) {
        this._read(rs.highWaterMark);
    }
};

Transform.prototype._doneTransforming = function (err) {
    if (err) {
        this.emit('error', err);
    }

    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = this._writableState,
        ts = this._transformState;

    if (ws.buffer.length) {
        throw new Error('Calling Transform#_doneTransforming when writable buffer not empty');
    }

    if (ts.transforming) {
        throw new Error('Calling Transform#_doneTransforming when still transforming');
    }

    return this.push(null);
};

function TransformState (opts, stream) {
    this.afterTransform = function (err, data) {
        return stream._afterTransform(err, data);
    };

    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
}
<|endoftext|>


<commit_before>var http = require('http');
var fs = require('fs');
var index = fs.readFileSync('index.html');

var testvals = [
        [45.507, -73.556, 3],
        [45.508, -73.556, 3],
        [45.509, -73.556, 2],
        [45.510, -73.556, 1],
        [45.511, -73.556, 2],
        [45.512, -73.556, 4],
        [45.513, -73.556, 2],
        [45.514, -73.513, 1]
];
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write(testvals);
    res.end(index);
}).listen(9615);

<commit_msg>update to express app<commit_after>var express = require('express');
var app = express();

var testvals = [
        [45.507, -73.556, 3],
        [45.508, -73.556, 3],
        [45.509, -73.556, 2],
        [45.510, -73.556, 1],
        [45.511, -73.556, 2],
        [45.512, -73.556, 4],
        [45.513, -73.556, 2],
        [45.514, -73.513, 1]
];
app.get('/data', function(req, res){
      res.send(testvals);
});

var server = app.listen(3000, function() {
        console.log('Listening on port %d', server.address().port);
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-2017 Memba Sarl. All rights reserved.
 * Sources at https://github.com/Memba
 */

/* jshint node: true */

'use strict';

var util = require('util');
var logger = require('./lib/logger');
var closingInProgress = false;

/**
 * Handle uncaught exceptions
 * @see http://stackoverflow.com/questions/7310521/node-js-best-practice-exception-handling
 */
process.on('uncaughtException', function (exception) {

    closingInProgress = true;

    logger.critical({
        // message = exception.message
        module: 'server',
        method: 'process.onuncaughtException',
        error: exception
    });

    if (typeof server !== 'undefined') {
        // stop taking new requests
        server.close();
        // make sure we close down within 5 seconds
        // which should give enough time for any pending request to complete
        var killtimer = setTimeout(function () {
            process.exit(1);
        }, 5 * 1000);
        // see https://nodejs.org/api/domain.html
        killtimer.unref();
    } else {
        process.exit(1);
    }

});

/**
 * Ensure we exit properly when interrupted by a kill
 */
process.on('SIGTERM', function () {
    // TODO pass exit code 0
    throw new Error('Process killed.');
});

/**
 * Ensure we exit properly when interrupting by Ctrl+C
 */
process.on('SIGINT', function () {
    // TODO pass exit code 0
    throw new Error('Process interrupted by Ctrl+C.');
});

/**
 * This event handler is called after process.exit
 * Therefore it closes the mongoose connection before exiting
 * either from an uncaughtException or from Ctrl+C
 */
process.on('exit', function (code) {
    // We use a try/catch block here because we might have reached here from an uncaughtException
    try {
        logger.warn({
            message: 'exiting with code ' + code,
            module: 'server',
            method: 'process.onexit'
        });
    } catch (ex) {
        // We use console.log because logger might not be available
        console.error(ex);
    }
});

var express = require('express');
var app = express();
var compression = require('compression');
var cors = require('cors');
var helmet = require('helmet');
var http = require('http');
var i18n = require('i18n');
var path = require('path');
var config = require('./config');
var pkg = require('../package.json');
var plugins = require('./plugins');
var redirect = require('./middleware/redirect');
var server;

logger.info({
    message: 'nconf environment is ' + config.environment,
    module: 'server'
});

/* This function has too many statements. */
/* jshint -W071 */

config.load(function (error/*, store*/) {

    if (error instanceof Error) {
        throw error;
    }

    // Redirect when necessary
    app.use(redirect.handler);

    // handle requests while closing
    app.use(function (req, res, next) {
        if (closingInProgress) {
            res.setHeader('Connection', 'close');
            res.status(503).send('A webapp server is in the process of restarting');
        } else {
            return next();
        }
    });

    // set version (to invalidate cache when loading new versions of scripts)
    config.set('application:version', pkg.version);

    // plugins
    plugins.load();

    // Secure expressJS with helmet from https://github.com/helmetjs/helmet
    // @see https://helmetjs.github.io/docs/csp/
    // @see https://content-security-policy.com/
    var cdnRoot = config.get('uris:cdn:root');
    var connectSrc = [
            '\'self\'',
            cdnRoot,                                // Required to load index.json on CDN
            'https://s3.amazonaws.com',             // Required to upload images to Amazon S3
            'https://js.leadin.com',                // Hubspot
            'https://forms.hubspot.com'             // Hubspot
            // 'https://api.getsidekick.com'
        ];
    var rapiRoot = config.get('uris:rapi:root');
    if (typeof rapiRoot === 'string' && rapiRoot !== config.get('uris:webapp:root')) {
        // Note: config.get('uris:webapp:root') is covered by 'self'
        // connectSrc.push(config.get('uris:rapi:root'));
        connectSrc.unshift(rapiRoot);
    }
    app.use(helmet({
        contentSecurityPolicy: {
            directives: {
                defaultSrc: [
                    '\'self\'',
                    'blob:'                             // Fallback for workerSrc
                ],
                connectSrc: connectSrc,
                fontSrc: [
                    '\'self\'',
                    'data:',
                    cdnRoot,
                    'https://fonts.gstatic.com'         // Google fonts
                ],
                childSrc: [ // was frameSrc
                    'blob:',                            // Fallback for workerSrc
                    'https://accounts.google.com',      // Google classroom button
                    'https://www.gstatic.com'           // Google classroom button
                ],
                imgSrc: [
                    'data:',
                    '*'
                ],
                mediaSrc: [
                    '*'
                ],
                scriptSrc: [
                    'blob:',                            // for workerSrc considering the 'child-src' directive is deprecated and will be removed in Chrome M60, around August 2017. Please use the 'script-src' directive for Workers instead.
                    '\'self\'',
                    '\'unsafe-eval\'',
                    '\'unsafe-inline\'',
                    cdnRoot,
                    'https://code.jquery.com',
                    'https://cdnjs.cloudflare.com',     // Promise polyfill for webpack
                    'https://www.googletagmanager.com', // GTM
                    'https://apis.google.com',          // Google classroom button
                    'www.google-analytics.com',         // Google Analytics (Loaded via http on http://localhost)
                    'js.hs-analytics.net',              // Hubspot (Loaded via http on http://localhost)
                    'https://api.usemessages.com',      // Hubspot
                    'https://js.hscollectedforms.net',  // Hubspot
                    'https://js.hsleadflows.net',       // Hubspot
                    'https://js.hsleadflowsqa.net',     // Hubspot
                    'https://js.hs-scripts.com',        // Hubspot
                    'https://js.leadin.com'             // Hubspot
                ],
                styleSrc: [
                    '\'self\'',
                    '\'unsafe-inline\'',
                    cdnRoot,
                    'https://fonts.googleapis.com'      // Google fonts
                ],
                // sandbox: ['allow-forms', 'allow-scripts'],
                // reportUri: '/report-violation',
                objectSrc: [
                    '\'none\''
                ] /*,
                workerSrc: [  // Not supported by helmet.contentSecurityPolicy
                    'blob:'
                ]
                */
            },
            browserSniff: false
        },
        frameguard: false
    }));

    // i18n
    i18n.configure({
        locales: config.get('locales'), // ['en', 'fr'],
        directory: path.join(__dirname, 'locales'),
        objectNotation: true, // Use hierarchies in locales.json files
        updateFiles: false,
        syncFiles: false
    });
    // Use __() in templates
    app.use(i18n.init);

    // Template engine
    app.engine('.ejs', require('ejs').__express);
    // Optional since express defaults to CWD/views
    app.set('views', path.join(__dirname, 'views'));
    // Without this one would need to supply the extension to res.render(), ex: res.render('users.html').
    app.set('view engine', 'ejs');

    // compression (before static files otherwise they are not compressed)
    app.use(compression({ filter: function (req, res) {
            if (req.headers['x-no-compression']) {
                // don't compress responses with this request header
                return false;
            }
            // fallback to standard filter function
            return compression.filter(req, res);
        }
    }));

    // Static files (before routing)
    // Cache-Control maxAge requires a string in MS format - see https://www.npmjs.com/package/ms
    app.use(
        util.format(config.get('uris:webapp:public'), ''),
        cors({ origin: config.get('uris:webapp:root') }),
        express.static(path.join(__dirname, 'public'), { maxAge: '1d' })
    );

    // Routing
    var router = require('./routes');
    app.use(router);

    // Configure expressJS and launch server
    var port = process.env.PORT || config.get('express:port');
    app.set('port', port);
    app.set('trust proxy', 'uniquelocal');
    server = app.listen(port);

    // Logging
    logger.info({
        message: 'expressJS server listening on port ' + port,
        module: 'server',
        method: 'config.load'
    });

});

/* jshint +W071 */

// Export app for unit tests
// It is fine, because app does not accept requests
// until it has been fully configured here above
module.exports = app;
<commit_msg>Fixed jscs and jshint errors<commit_after>/**
 * Copyright (c) 2013-2017 Memba Sarl. All rights reserved.
 * Sources at https://github.com/Memba
 */

/* jshint node: true */

'use strict';

var util = require('util');
var logger = require('./lib/logger');
var closingInProgress = false;

/**
 * Handle uncaught exceptions
 * @see http://stackoverflow.com/questions/7310521/node-js-best-practice-exception-handling
 */
process.on('uncaughtException', function (exception) {

    closingInProgress = true;

    logger.critical({
        // message = exception.message
        module: 'server',
        method: 'process.onuncaughtException',
        error: exception
    });

    if (typeof server !== 'undefined') {
        // stop taking new requests
        server.close();
        // make sure we close down within 5 seconds
        // which should give enough time for any pending request to complete
        var killtimer = setTimeout(function () {
            process.exit(1);
        }, 5 * 1000);
        // see https://nodejs.org/api/domain.html
        killtimer.unref();
    } else {
        process.exit(1);
    }

});

/**
 * Ensure we exit properly when interrupted by a kill
 */
process.on('SIGTERM', function () {
    // TODO pass exit code 0
    throw new Error('Process killed.');
});

/**
 * Ensure we exit properly when interrupting by Ctrl+C
 */
process.on('SIGINT', function () {
    // TODO pass exit code 0
    throw new Error('Process interrupted by Ctrl+C.');
});

/**
 * This event handler is called after process.exit
 * Therefore it closes the mongoose connection before exiting
 * either from an uncaughtException or from Ctrl+C
 */
process.on('exit', function (code) {
    // We use a try/catch block here because we might have reached here from an uncaughtException
    try {
        logger.warn({
            message: 'exiting with code ' + code,
            module: 'server',
            method: 'process.onexit'
        });
    } catch (ex) {
        // We use console.log because logger might not be available
        console.error(ex);
    }
});

var express = require('express');
var app = express();
var compression = require('compression');
var cors = require('cors');
var helmet = require('helmet');
var http = require('http');
var i18n = require('i18n');
var path = require('path');
var config = require('./config');
var pkg = require('../package.json');
var plugins = require('./plugins');
var redirect = require('./middleware/redirect');
var server;

logger.info({
    message: 'nconf environment is ' + config.environment,
    module: 'server'
});

/* This function has too many statements. */
/* jshint -W071 */

config.load(function (error/*, store*/) {

    if (error instanceof Error) {
        throw error;
    }

    // Redirect when necessary
    app.use(redirect.handler);

    // handle requests while closing
    app.use(function (req, res, next) {
        if (closingInProgress) {
            res.setHeader('Connection', 'close');
            res.status(503).send('A webapp server is in the process of restarting');
        } else {
            return next();
        }
    });

    // set version (to invalidate cache when loading new versions of scripts)
    config.set('application:version', pkg.version);

    // plugins
    plugins.load();

    // Secure expressJS with helmet from https://github.com/helmetjs/helmet
    // @see https://helmetjs.github.io/docs/csp/
    // @see https://content-security-policy.com/
    var cdnRoot = config.get('uris:cdn:root');
    var connectSrc = [
            '\'self\'',
            cdnRoot,                                // Required to load index.json on CDN
            'https://s3.amazonaws.com',             // Required to upload images to Amazon S3
            'https://js.leadin.com',                // Hubspot
            'https://forms.hubspot.com'             // Hubspot
            // 'https://api.getsidekick.com'
        ];
    var rapiRoot = config.get('uris:rapi:root');
    if (typeof rapiRoot === 'string' && rapiRoot !== config.get('uris:webapp:root')) {
        // Note: config.get('uris:webapp:root') is covered by 'self'
        // connectSrc.push(config.get('uris:rapi:root'));
        connectSrc.unshift(rapiRoot);
    }
    app.use(helmet({
        contentSecurityPolicy: {
            directives: {
                defaultSrc: [
                    '\'self\'',
                    'blob:'                             // Fallback for workerSrc
                ],
                connectSrc: connectSrc,
                fontSrc: [
                    '\'self\'',
                    'data:',
                    cdnRoot,
                    'https://fonts.gstatic.com'         // Google fonts
                ],
                childSrc: [// was frameSrc
                    'blob:',                            // Fallback for workerSrc
                    'https://accounts.google.com',      // Google classroom button
                    'https://www.gstatic.com'           // Google classroom button
                ],
                imgSrc: [
                    'data:',
                    '*'
                ],
                mediaSrc: [
                    '*'
                ],
                scriptSrc: [
                    'blob:',                            // for workerSrc considering the 'child-src' directive is deprecated and will be removed in Chrome M60, around August 2017. Please use the 'script-src' directive for Workers instead.
                    '\'self\'',
                    '\'unsafe-eval\'',
                    '\'unsafe-inline\'',
                    cdnRoot,
                    'https://code.jquery.com',
                    'https://cdnjs.cloudflare.com',     // Promise polyfill for webpack
                    'https://www.googletagmanager.com', // GTM
                    'https://apis.google.com',          // Google classroom button
                    'www.google-analytics.com',         // Google Analytics (Loaded via http on http://localhost)
                    'js.hs-analytics.net',              // Hubspot (Loaded via http on http://localhost)
                    'https://api.usemessages.com',      // Hubspot
                    'https://js.hscollectedforms.net',  // Hubspot
                    'https://js.hsleadflows.net',       // Hubspot
                    'https://js.hsleadflowsqa.net',     // Hubspot
                    'https://js.hs-scripts.com',        // Hubspot
                    'https://js.leadin.com'             // Hubspot
                ],
                styleSrc: [
                    '\'self\'',
                    '\'unsafe-inline\'',
                    cdnRoot,
                    'https://fonts.googleapis.com'      // Google fonts
                ],
                // sandbox: ['allow-forms', 'allow-scripts'],
                // reportUri: '/report-violation',
                objectSrc: [
                    '\'none\''
                ] /*,
                workerSrc: [  // Not supported by helmet.contentSecurityPolicy
                    'blob:'
                ]
                */
            },
            browserSniff: false
        },
        frameguard: false
    }));

    // i18n
    i18n.configure({
        locales: config.get('locales'), // ['en', 'fr'],
        directory: path.join(__dirname, 'locales'),
        objectNotation: true, // Use hierarchies in locales.json files
        updateFiles: false,
        syncFiles: false
    });
    // Use __() in templates
    app.use(i18n.init);

    // Template engine
    app.engine('.ejs', require('ejs').__express);
    // Optional since express defaults to CWD/views
    app.set('views', path.join(__dirname, 'views'));
    // Without this one would need to supply the extension to res.render(), ex: res.render('users.html').
    app.set('view engine', 'ejs');

    // compression (before static files otherwise they are not compressed)
    app.use(compression({ filter: function (req, res) {
            if (req.headers['x-no-compression']) {
                // don't compress responses with this request header
                return false;
            }
            // fallback to standard filter function
            return compression.filter(req, res);
        }
    }));

    // Static files (before routing)
    // Cache-Control maxAge requires a string in MS format - see https://www.npmjs.com/package/ms
    app.use(
        util.format(config.get('uris:webapp:public'), ''),
        cors({ origin: config.get('uris:webapp:root') }),
        express.static(path.join(__dirname, 'public'), { maxAge: '1d' })
    );

    // Routing
    var router = require('./routes');
    app.use(router);

    // Configure expressJS and launch server
    var port = process.env.PORT || config.get('express:port');
    app.set('port', port);
    app.set('trust proxy', 'uniquelocal');
    server = app.listen(port);

    // Logging
    logger.info({
        message: 'expressJS server listening on port ' + port,
        module: 'server',
        method: 'config.load'
    });

});

/* jshint +W071 */

// Export app for unit tests
// It is fine, because app does not accept requests
// until it has been fully configured here above
module.exports = app;
<|endoftext|>


<commit_before>(function () {

  /* On Linux, BLE normally needs admin right to be able to access BLE
  *
  * sudo apt-get install libcap2-bin
  * sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)
  */

  if (typeof require === 'undefined') return;
  var noble = undefined;
  try {
    noble = require('noble');
  } catch (e) {
    console.log("Noble: module couldn't be loaded, no node.js Bluetooth Low Energy\n", e);
    // super nasty workaround for https://github.com/sandeepmistry/noble/issues/502
    process.removeAllListeners('exit');
    return;
  }

  var NORDIC_SERVICE = "6e400001b5a3f393e0a9e50e24dcca9e";
  var NORDIC_TX = "6e400002b5a3f393e0a9e50e24dcca9e";
  var NORDIC_RX = "6e400003b5a3f393e0a9e50e24dcca9e";
  var NORDIC_TX_MAX_LENGTH = 20;

  var initialised = false;
  var errored = false;
  var scanWhenInitialised = undefined;

  function findByUUID(list, uuid) {
    for (var i=0;i<list.length;i++)
      if (list[i].uuid==uuid) return list[i];
    return undefined;
  }

  // map of bluetooth devices found by getPorts
  var btDevices = {};
  var newDevices = [];
  var lastDevices = [];

  var btDevice;
  var txCharacteristic;
  var rxCharacteristic;
  var txInProgress = false;
  var scanStopTimeout = undefined;

  function init() {
    Espruino.Core.Config.add("BLUETOOTH_LOW_ENERGY", {
      section: "Communications",
      name: "Connect over Bluetooth Smart (BTLE) via 'noble'",
      descriptionHTML: 'Allow connection to Espruino via BLE with the Nordic UART implementation',
      type: "boolean",
      defaultValue: true
    });
  }

  noble.on('stateChange', function(state) {
    console.log("Noble: stateChange -> "+state);
    if (state=="poweredOn") {
      if (Espruino.Config.WEB_BLUETOOTH) {
        // Everything has already initialised, so we must disable
        // web bluetooth this way instead
        console.log("Noble: Disable Web Bluetooth as we have Noble instead");
        Espruino.Config.WEB_BLUETOOTH = false;
      }
      initialised = true;
      /* if getPorts was called before initialisation, be sure
      to wait for stuff to arrive before just calling back
      with nothing - we're in the CLI */
      if (scanWhenInitialised) {
        var scb = scanWhenInitialised;
        scanWhenInitialised = undefined;
        getPorts(function() {
          setTimeout(function() {
            getPorts(scb);
          }, 1500);
        });
      }
    }
    if (state=="poweredOff") {
      initialised = false;
      if (scanWhenInitialised) {
        var scb = scanWhenInitialised;
        scanWhenInitialised = undefined;
        scb(undefined, true/*instantPorts*/);
      }
    }
  });
  // if we didn't initialise for whatever reason, keep going anyway
  setTimeout(function() {
    if (initialised) return;
    console.log("Noble: Didn't initialise in 10 seconds, disabling.");
    errored = true;
    if (scanWhenInitialised) {
      scanWhenInitialised([]);
      scanWhenInitialised = undefined;
    }
  }, 10000);

  noble.on('discover', function(dev) {
    if (!dev.advertisement) return;
    for (var i in newDevices)
      if (newDevices[i].path == dev.address) return; // already seen it
    var name = dev.advertisement.localName;
    var hasUartService = dev.advertisement.serviceUuids.indexOf(NORDIC_SERVICE)>=0;
    if (hasUartService ||
        Espruino.Core.Utils.isRecognisedBluetoothDevice(name)) {
      console.log("Noble: Found UART device:", name, dev.address);
      newDevices.push({ path: dev.address, description: name, type : "bluetooth" });
      btDevices[dev.address] = dev;
    } else console.log("Noble: Found device:", name, dev.address);
  });

  var getPorts = function (callback) {
    if (errored || !Espruino.Config.BLUETOOTH_LOW_ENERGY) {
      console.log("Noble: getPorts - disabled");
      callback([], true/*instantPorts*/);
    } else if (!initialised) {
      console.log("Noble: getPorts - not initialised");
      // if not initialised yet, wait until we are
      if (scanWhenInitialised) scanWhenInitialised([]);
      scanWhenInitialised = callback;
    } else { // all ok - let's go!
      // Ensure we're scanning
      if (scanStopTimeout) {
        clearTimeout(scanStopTimeout);
        scanStopTimeout = undefined;
      } else {
        console.log("Noble: Starting scan");
        lastDevices = [];
        newDevices = [];
        noble.startScanning([], true);
      }
      scanStopTimeout = setTimeout(function () {
        scanStopTimeout = undefined;
        console.log("Noble: Stopping scan");
        noble.stopScanning();
      }, 3000);
      // report back device list from both the last scan and this one...
      var reportedDevices = [];
      newDevices.forEach(function (d) {
        reportedDevices.push(d);
      });
      lastDevices.forEach(function (d) {
        var found = false;
        reportedDevices.forEach(function (dv) {
          if (dv.path == d.path) found = true;
        });
        if (!found) reportedDevices.push(d);
      });
      reportedDevices.sort(function (a, b) { return a.path.localeCompare(b.path); });
      lastDevices = newDevices;
      newDevices = [];
      //console.log("Noble: reportedDevices",reportedDevices);
      callback(reportedDevices, false/*instantPorts*/);
    }
  };

  var openSerial = function (serialPort, openCallback, receiveCallback, disconnectCallback) {
    btDevice = btDevices[serialPort];
    if (btDevice === undefined) throw "BT device not found"

    if (scanStopTimeout) {
      clearTimeout(scanStopTimeout);
      scanStopTimeout = undefined;
      console.log("Noble: Stopping scan (openSerial)");
      noble.stopScanning();
    }

    txInProgress = false;

    console.log("BT> Connecting");
    btDevice.on('disconnect', function() {
      txCharacteristic = undefined;
      rxCharacteristic = undefined;
      btDevice = undefined;
      txInProgress = false;
      disconnectCallback();
    });

    btDevice.connect(function (error) {
      if (error) {
        console.log("BT> ERROR Connecting");
        btDevice = undefined;
        return openCallback();
      }
      console.log("BT> Connected");

      btDevice.discoverAllServicesAndCharacteristics(function(error, services, characteristics) {
        var btUARTService = findByUUID(services, NORDIC_SERVICE);
        txCharacteristic = findByUUID(characteristics, NORDIC_TX);
        rxCharacteristic = findByUUID(characteristics, NORDIC_RX);
        if (error || !btUARTService || !txCharacteristic || !rxCharacteristic) {
          console.log("BT> ERROR getting services/characteristics");
          console.log("Service "+btUARTService);
          console.log("TX "+txCharacteristic);
          console.log("RX "+rxCharacteristic);
          btDevice.disconnect();
          txCharacteristic = undefined;
          rxCharacteristic = undefined;
          btDevice = undefined;
          return openCallback();
        }

        rxCharacteristic.on('data', function (data) {
          receiveCallback(new Uint8Array(data).buffer);
        });
        rxCharacteristic.subscribe(function() {
          openCallback({});
        });
      });
    });
  };

  var closeSerial = function () {
    if (btDevice) {
      btDevice.disconnect(); // should call disconnect callback?
    }
  };

  // Throttled serial write
  var writeSerial = function (data, callback) {
    if (txCharacteristic === undefined) return;

    if (data.length>NORDIC_TX_MAX_LENGTH) {
      console.error("BT> TX length >"+NORDIC_TX_MAX_LENGTH);
      return callback();
    }
    if (txInProgress) {
      console.error("BT> already sending!");
      return callback();
    }

    console.log("BT> send "+JSON.stringify(data));
    txInProgress = true;
    try {
      txCharacteristic.write(Espruino.Core.Utils.stringToBuffer(data), false, function() {
        txInProgress = false;
        return callback();
      });
    } catch (e) {
      console.log("BT> SEND ERROR " + e);
      closeSerial();
    }
  };

  // ----------------------------------------------------------

  Espruino.Core.Serial.devices.push({
    "name" : "Noble Bluetooth LE",
    "init": init,
    "getPorts": getPorts,
    "open": openSerial,
    "write": writeSerial,
    "close": closeSerial,
    "maxWriteLength" : NORDIC_TX_MAX_LENGTH,
  });
})();
<commit_msg>Only start Noble after first getPorts<commit_after>(function () {

  /* On Linux, BLE normally needs admin right to be able to access BLE
  *
  * sudo apt-get install libcap2-bin
  * sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)
  */

  if (typeof require === 'undefined') return;
  var noble = undefined;

  var NORDIC_SERVICE = "6e400001b5a3f393e0a9e50e24dcca9e";
  var NORDIC_TX = "6e400002b5a3f393e0a9e50e24dcca9e";
  var NORDIC_RX = "6e400003b5a3f393e0a9e50e24dcca9e";
  var NORDIC_TX_MAX_LENGTH = 20;

  var initialised = false;
  var errored = false;
  var scanWhenInitialised = undefined;

  function findByUUID(list, uuid) {
    for (var i=0;i<list.length;i++)
      if (list[i].uuid==uuid) return list[i];
    return undefined;
  }

  // map of bluetooth devices found by getPorts
  var btDevices = {};
  var newDevices = [];
  var lastDevices = [];

  var btDevice;
  var txCharacteristic;
  var rxCharacteristic;
  var txInProgress = false;
  var scanStopTimeout = undefined;

  function init() {
    Espruino.Core.Config.add("BLUETOOTH_LOW_ENERGY", {
      section: "Communications",
      name: "Connect over Bluetooth Smart (BTLE) via 'noble'",
      descriptionHTML: 'Allow connection to Espruino via BLE with the Nordic UART implementation',
      type: "boolean",
      defaultValue: true
    });
  }

  function startNoble() {
    try {
      noble = require('noble');
    } catch (e) {
      console.log("Noble: module couldn't be loaded, no node.js Bluetooth Low Energy\n", e);
      // super nasty workaround for https://github.com/sandeepmistry/noble/issues/502
      process.removeAllListeners('exit');
      errored = true;
      return;
    }

    noble.on('stateChange', function(state) {
      console.log("Noble: stateChange -> "+state);
      if (state=="poweredOn") {
        if (Espruino.Config.WEB_BLUETOOTH) {
          // Everything has already initialised, so we must disable
          // web bluetooth this way instead
          console.log("Noble: Disable Web Bluetooth as we have Noble instead");
          Espruino.Config.WEB_BLUETOOTH = false;
        }
        initialised = true;
        /* if getPorts was called before initialisation, be sure
        to wait for stuff to arrive before just calling back
        with nothing - we're in the CLI */
        if (scanWhenInitialised) {
          var scb = scanWhenInitialised;
          scanWhenInitialised = undefined;
          getPorts(function() {
            setTimeout(function() {
              getPorts(scb);
            }, 1500);
          });
        }
      }
      if (state=="poweredOff") {
        initialised = false;
        if (scanWhenInitialised) {
          var scb = scanWhenInitialised;
          scanWhenInitialised = undefined;
          scb(undefined, true/*instantPorts*/);
        }
      }
    });

    noble.on('discover', function(dev) {
      if (!dev.advertisement) return;
      for (var i in newDevices)
        if (newDevices[i].path == dev.address) return; // already seen it
      var name = dev.advertisement.localName;
      var hasUartService = dev.advertisement.serviceUuids.indexOf(NORDIC_SERVICE)>=0;
      if (hasUartService ||
          Espruino.Core.Utils.isRecognisedBluetoothDevice(name)) {
        console.log("Noble: Found UART device:", name, dev.address);
        newDevices.push({ path: dev.address, description: name, type : "bluetooth" });
        btDevices[dev.address] = dev;
      } else console.log("Noble: Found device:", name, dev.address);
    });

    // if we didn't initialise for whatever reason, keep going anyway
    setTimeout(function() {
      if (initialised) return;
      console.log("Noble: Didn't initialise in 10 seconds, disabling.");
      errored = true;
      if (scanWhenInitialised) {
        scanWhenInitialised([]);
        scanWhenInitialised = undefined;
      }
    }, 10000);
  }

  var getPorts = function (callback) {
    if (errored || !Espruino.Config.BLUETOOTH_LOW_ENERGY) {
      console.log("Noble: getPorts - disabled");
      callback([], true/*instantPorts*/);
    } else if (!initialised) {
      if (!noble) startNoble();
      console.log("Noble: getPorts - not initialised");
      // if not initialised yet, wait until we are
      if (scanWhenInitialised) scanWhenInitialised([]);
      scanWhenInitialised = callback;
    } else { // all ok - let's go!
      // Ensure we're scanning
      if (scanStopTimeout) {
        clearTimeout(scanStopTimeout);
        scanStopTimeout = undefined;
      } else {
        console.log("Noble: Starting scan");
        lastDevices = [];
        newDevices = [];
        noble.startScanning([], true);
      }
      scanStopTimeout = setTimeout(function () {
        scanStopTimeout = undefined;
        console.log("Noble: Stopping scan");
        noble.stopScanning();
      }, 3000);
      // report back device list from both the last scan and this one...
      var reportedDevices = [];
      newDevices.forEach(function (d) {
        reportedDevices.push(d);
      });
      lastDevices.forEach(function (d) {
        var found = false;
        reportedDevices.forEach(function (dv) {
          if (dv.path == d.path) found = true;
        });
        if (!found) reportedDevices.push(d);
      });
      reportedDevices.sort(function (a, b) { return a.path.localeCompare(b.path); });
      lastDevices = newDevices;
      newDevices = [];
      //console.log("Noble: reportedDevices",reportedDevices);
      callback(reportedDevices, false/*instantPorts*/);
    }
  };

  var openSerial = function (serialPort, openCallback, receiveCallback, disconnectCallback) {
    btDevice = btDevices[serialPort];
    if (btDevice === undefined) throw "BT device not found"

    if (scanStopTimeout) {
      clearTimeout(scanStopTimeout);
      scanStopTimeout = undefined;
      console.log("Noble: Stopping scan (openSerial)");
      noble.stopScanning();
    }

    txInProgress = false;

    console.log("BT> Connecting");
    btDevice.on('disconnect', function() {
      txCharacteristic = undefined;
      rxCharacteristic = undefined;
      btDevice = undefined;
      txInProgress = false;
      disconnectCallback();
    });

    btDevice.connect(function (error) {
      if (error) {
        console.log("BT> ERROR Connecting");
        btDevice = undefined;
        return openCallback();
      }
      console.log("BT> Connected");

      btDevice.discoverAllServicesAndCharacteristics(function(error, services, characteristics) {
        var btUARTService = findByUUID(services, NORDIC_SERVICE);
        txCharacteristic = findByUUID(characteristics, NORDIC_TX);
        rxCharacteristic = findByUUID(characteristics, NORDIC_RX);
        if (error || !btUARTService || !txCharacteristic || !rxCharacteristic) {
          console.log("BT> ERROR getting services/characteristics");
          console.log("Service "+btUARTService);
          console.log("TX "+txCharacteristic);
          console.log("RX "+rxCharacteristic);
          btDevice.disconnect();
          txCharacteristic = undefined;
          rxCharacteristic = undefined;
          btDevice = undefined;
          return openCallback();
        }

        rxCharacteristic.on('data', function (data) {
          receiveCallback(new Uint8Array(data).buffer);
        });
        rxCharacteristic.subscribe(function() {
          openCallback({});
        });
      });
    });
  };

  var closeSerial = function () {
    if (btDevice) {
      btDevice.disconnect(); // should call disconnect callback?
    }
  };

  // Throttled serial write
  var writeSerial = function (data, callback) {
    if (txCharacteristic === undefined) return;

    if (data.length>NORDIC_TX_MAX_LENGTH) {
      console.error("BT> TX length >"+NORDIC_TX_MAX_LENGTH);
      return callback();
    }
    if (txInProgress) {
      console.error("BT> already sending!");
      return callback();
    }

    console.log("BT> send "+JSON.stringify(data));
    txInProgress = true;
    try {
      txCharacteristic.write(Espruino.Core.Utils.stringToBuffer(data), false, function() {
        txInProgress = false;
        return callback();
      });
    } catch (e) {
      console.log("BT> SEND ERROR " + e);
      closeSerial();
    }
  };

  // ----------------------------------------------------------

  Espruino.Core.Serial.devices.push({
    "name" : "Noble Bluetooth LE",
    "init": init,
    "getPorts": getPorts,
    "open": openSerial,
    "write": writeSerial,
    "close": closeSerial,
    "maxWriteLength" : NORDIC_TX_MAX_LENGTH,
  });
})();
<|endoftext|>


<commit_before>/*global React:true, ReactDOM:true, require:true */
/* exported React, ReactDOM */
React = require('react');
ReactDOM = require('react-dom');
iframePhone = require('iframe-phone');
Papa = require('papaparse');
L = require('leaflet');
L.esri = require('esri-leaflet');
deepEqual = require('deep-equal');
Promise = require('es6-promise').Promise;
<commit_msg>[#140457281] Add pluralize to bundle definition.<commit_after>/*global React:true, ReactDOM:true, require:true */
/* exported React, ReactDOM */
React = require('react');
ReactDOM = require('react-dom');
iframePhone = require('iframe-phone');
Papa = require('papaparse');
L = require('leaflet');
L.esri = require('esri-leaflet');
deepEqual = require('deep-equal');
Promise = require('es6-promise').Promise;
pluralize = require('pluralize');
<|endoftext|>