Javascript init function breaks because of this keyword? - javascript

I'm having issues writing my JavaScript/Jquery correctly because I'm a newbie. I have a couple of functions that are breaking each other because of the this keyword. All of the functions that are breaking are listed below and the last one is what causes me to know that it is the this keyword:
// Functions that break
var gp;
gp = function() {
var autocomplete, input, types;
input = document.getElementById('loc-input');
types = document.getElementById('type-selector');
autocomplete = new google.maps.places.Autocomplete(input);
};
google.maps.event.addDomListener(window, 'load', gp);
$('a[href="' + this.location.pathname + '"]').parent('.navbar-nav li').addClass('active');
$('ul.nav li.dropdown, .dropdown-hover').hover((function() {
$(this).find('.dropdown-menu').stop(true, true).delay(50).fadeIn();
}), function() {
$(this).find('.dropdown-menu').stop(true, true).delay(50).fadeOut();
});
$('.form-control').mousedown(function() {
if (!$(this).is(':focus')) {
return;
}
$(this).blur().focus();
});
$('#new_item').dropzone({
acceptedFiles: '.jpeg, .jpg, .png',
// Area that causes functions to break
init: function() {
var myDropzone;
myDropzone = this;
this.element.querySelector('button[type=submit]').addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
this.on('sendingmultiple', function() {});
this.on('successmultiple', function(files, response) {});
this.on('errormultiple', function(files, response) {});
}
});
This area right here (inner function) if commented out makes all the JavaScript work again but if used, all is lost:
init: function() {
var myDropzone;
myDropzone = this;
this.element.querySelector('button[type=submit]').addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
this.on('sendingmultiple', function() {});
this.on('successmultiple', function(files, response) {});
this.on('errormultiple', function(files, response) {});
}
So I'm trying to figure how I can get all of these functions to work as they should or without the use of the this keyword and still self-reference?
Edit
So with the Chrome extension: Javascript Errors Notifier. I was able to see the error saying:
TypeError: Cannot read property 'addEventListener' of null
I made a gist of the returned JavaScript here:
https://gist.github.com/justintech/d6d5bdb8468b79f60663
Edit 2 - The form
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<form data-validate="true" class="form-horizontal form" id="new_item" enctype="multipart/form-data" action="/items" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="/pbJ8IQK+ybIrjXFD7t2MIWzzFKsvmF7DA9oKSnNxouMk6i+jLNsboDZELHM5+w2qEnE0qzBEXyNFGl7HB85kQ==">
<fieldset>
</div>
<main id="image-preview" class="dz-clickable">
</main>
<div class="submit-section">
<div class="col-lg-12 col-md-12">
<input type="submit" name="commit" value="Done" id="item-submit" class="btn btn-primary btn-lg btn-block">
</div>
</div>
</fieldset>
</form>
</div>
</div>

Using this
document.querySelector('#item-submit')
instead of this
this.element.querySelector('button[type=submit]')
will fix the problem you are seeing. Will that work for you?

Related

How to add remove class of div on input:file's onchange event?

<html>
<form class="form" id="helpForm" enctype='multipart/form-data' novalidate>
<div id="file_div" class="form-group">
<div class="controls">
<input type="file" id="file_upload" class="form-control square" accept="application/pdf" name="file_upload" onchange="return fileValidation()">
<div class="help-block" id="file_error"></div>
</div>
</div>
<button type="submit" class="btn btn-primary" id="form-submit">submit</button>
</form>
</html>
I have written some jquery code to work with it
function fileValidation() {
var fileInput = document.getElementById('file_upload');
var filePath = fileInput.value;
// Allowing file type
var allowedExtensions = /(\.pdf)$/i;
if(fileInput.files[0] == undefined) {
$('#file_div').removeClass('validate');
$("#file_div").addClass('error');
$('#file_error').css('display','block');
$('#file_error').append('<ul role="alert"><li>Pdf File is required field !</li></ul>');
return false;
} else if (!allowedExtensions.exec(filePath)) {
$('#file_div').removeClass('validate');
$("#file_div").addClass('error');
$('#file_error').css('display','block');
$('#file_error').append('<ul role="alert"><li>File type is not allowed !</li></ul>');
return false;
} else if (fileInput.files[0].size > 2097152) { //26214400 -25MB
$('#file_div').removeClass('validate');
$("#file_div").addClass('error');
$('#file_error').css('display','block');
$('#file_error').append('<ul role="alert"><li>File size must under 2MB !</li></ul>');
return false;
} else {
if (event == undefined) {
uploadFile();
}
return true;
}
}
if I do console.log() inside fileValidation() it print everything here.
but why my this code not doing its work?
$('#file_div').removeClass('validate');
$("#file_div").addClass('error');
$('#file_error').css('display','block');
$('#file_error').append('<ul role="alert"><li>Pdf File is required field !</li></ul>');
It work if I call fileValidation() on submit button.
Things to I am using for other validation. and inside this
(function(window, document, $) {
'use strict';
// Input, Select, Textarea validations except submit button
$("input,select,textarea,file").not("[type=submit]").jqBootstrapValidation({
filter: function () {
return $(this).is(":visible");
},
sniffHtml: false,
submitSuccess: function ($form, event) {
event.preventDefault();
fileValidation(); // this is working and doing all
}
});
})(window, document, jQuery);
Can anyone suggest , how I can achieve this on OnChange event?
Thanks
The issue here is $("input,select,textarea,file").not("[type=submit]").jqBootstrapValidation({}); function.
So if anyone help to find why it blocking that onchange function to work?

google invisible recaptcha keeps running without execute

I'm trying to use google invisible recaptcha on my web form (php and codeigniter 3). but somehow whenever I click on the Submit button, the google recaptcha keeps generating questions as if ignoring all the other codes before the execute command. so none of the console.log and alert ever appear. what is wrong with my code?
my code looks like this:
HTML
<form id="form_signup" method="post" action="/signup">
<input type="text" name="username"/>
<div class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="<?php echo $mysitekey; ?>"
data-callback="onSubmitFormSignupUser">
</div>
<button type="button" id="formSignup-btnSubmit">
Submit
</button>
</form>
JS
var widgetId = '';
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render('formSignup-btnSubmit', {
'sitekey' : $('#form_signup-recaptcha').attr('data-sitekey'),
'callback' : $('#form_signup-recaptcha').attr('data-callback'),
});
};
var onSubmitFormSignupUser = function(response) {
console.log('response', response);
if ($('[name="username"]').val()) {
alert('yes');
grecaptcha.execute(widgetId);
doSubmitFormToServer('#form_signup');
}
else {
alert('no');
grecaptcha.reset(widgetId);
}
}
var doSubmitFormToServer = function(selector) {
var myData = $(selector).serializeArray();
console.log('send form data', myData);
}
Well, you had a typo in the id, at least, here id="form_signup-recaptcha" and here: 'sitekey' : $('#formSignup-recaptcha').attr('data-sitekey'),, other than that, it is not clear, was it invoked at all, or not, as you've not provided the part of including the script, which should contain ?onload=onLoadRecaptcha parameter.
The code is below, but it won't work here, because of null origin. Check Codepen instead: https://codepen.io/extempl/pen/abOvBZv
sitekey used is one is for testing purposes only, as described here: https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha-v2-what-should-i-do
var widgetId = "";
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("formSignup-btnSubmit", {
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
var onSubmitFormSignupUser = function(response) {
console.log("response", response);
if ($('[name="username"]').val()) {
grecaptcha.execute(widgetId);
doSubmitFormToServer("#form_signup");
} else {
$(".status").text("failed");
grecaptcha.reset(widgetId);
}
};
var doSubmitFormToServer = function(selector) {
var myData = $(selector).serializeArray();
$(".status").text("submitted");
console.log("send form data", myData);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?onload=onLoadRecaptcha"></script>
<body>
<form id="form_signup" method="post" action="/signup">
<input type="text" name="username" />
<div
class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
data-callback="onSubmitFormSignupUser">
</div>
<button type="button" id="formSignup-btnSubmit">
Submit
</button>
<span class="status"></span>
</form>
</body>
it turns out that the solution is so simple.
this code
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("formSignup-btnSubmit", { // wrong element ID
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
should be like this
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("form_signup-recaptcha", { // corrent element ID
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
because the recaptcha element is like this
<div
class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
data-callback="onSubmitFormSignupUser">
</div>
so basically the parameters for grecaptcha.render should follow the properties in the element that has g-recaptcha class. my mistake was that I used the button id, even though the element with g-recaptcha class was the div.
I don't remember reading about this particular thing in the documentation. I guess I'm too stupid to realize that before this.. I hope this makes things clear for others with the same problem.

Meteor - preventDefault not preventing default

I'm busy with David Turnbull's - Your first Meteor Application. Everything works up to the point where I try and add a new player to the list via a form. My problem is that preventDefault is not preventing the form from trying to submit and reloading the page. return false doesn't work either.
Any ideas why this will be happening?
Thanks
PlayersList = new Mongo.Collection('players');
if (Meteor.isClient) {
//Helpers
Template.leaderboard.helpers({
'player': function() {
return PlayersList.find({}, {sort: {score: -1, name: 1}});
},
'playerCount': function() {
return PlayersList.find().count();
},
'selectedClass': function() {
var playerId = this._id;
var selectedPlayer = Session.get('selectedPlayer');
if(playerId == selectedPlayer) {
return 'selected'
}
},
'showSelectedPlayer': function() {
var selectedPlayer = Session.get('selectedPlayer');
return PlayersList.findOne(selectedPlayer);
}
});
//Events
Template.leaderboard.events({
'click .player': function() {
var playerId = this._id;
Session.set('selectedPlayer', playerId);
},
'click .increment': function() {
var selectedPlayer = Session.get('selectedPlayer');
var increaseBy = document.getElementById('increase-by').value;
var isNumber = /^\d+$/.test(increaseBy);
if(increaseBy != '' && isNumber) {
PlayersList.update(selectedPlayer, {$inc: {score: +increaseBy}});
}
},
'click .decrement': function() {
var selectedPlayer = Session.get('selectedPlayer');
var decreaseBy = document.getElementById('decrease-by').value;
PlayersList.update(selectedPlayer, {$inc: {score: -decreaseBy}});
},
'submit #new-player': function(event) {
event.preventDefault();
var playerNameVar = event.target.playerName.value;
if(playerNameVar != '') {
PlayersList.insert({
name: playerNameVar,
score:0
});
}
}
});
}
Template
<template name="addPlayerForm">
<div id="add-player" class="reveal-modal" data-reveal>
<a class="close-reveal-modal">×</a>
<h2>Add a player</h2>
<p class="lead">Add another player to the leaderboard</p>
<div class="row">
<div class="small-8 column small-centered">
<form id="new-player">
<div class="row collapse">
<div class="small-8 column">
<input type="text" placeholder="Player name" name="playerName">
</div>
<div class="small-4 column">
<input type="submit" class="button postfix" value="add player">
</div>
</div>
</form>
</div>
</div>
</div>
</template>
I've never read the book, and I don't know what your template looks like, but the problem is likely due to a selector issue.
Maybe try assigning an id to your form and mapping the submit event to that id:
// html file
<Template name="leaderboard">
<form id="new-player">
<input type="text" name="playerName">
<input type="submit" value="Submit">
</form>
</Template>
// js file
Template.leaderboard.events({
'submit #new-player': function(event) {
event.preventDefault();
...
}
});
Edit
Maybe try changing Template.leaderboard.events to Template.addPlayerForm.events.
Ok, I made the same mistake as the poster and I am putting the correct code here:
In html file:
<template name="addPlayerForm">
<form>
<input type="text" name="playerName">
<input type="submit" value="Add Player">
</form>
</template>
In js file:
Template.addPlayerForm.events({
'submit form': function(event){
event.preventDefault();
console.log("Form submitted");
console.log(event.type);
}
});

how to dynamically create the action attribute (URL) of my html form based on user input

Sorry - still a beginner - How do I dynamically create action url using the input text from the user?
<form name="myInstitution" action="" method="GET">
<div>
<label for="names" class="bold">Institution Name</label>
<input id="names" name="schoolName" type="text"></input>
</div>
<div class="bold"></div>
<div>
<input type="submit" value="Submit" id="sbutton" name="submit" />
<input type="reset" value="Reset" />
</div>
</form>
Since you don't seem to be using a javascript library, I'll copy the bind code in pure javascript from this answer.
var on = (function(){
if ("addEventListener" in window) {
return function(target, type, listener){
target.addEventListener(type, listener, false);
};
}
else {
return function(object, sEvent, fpNotify){
object.attachEvent("on" + sEvent, function(){
fpNotify(window.event);
});
};
}
}());
on(document.getElementById("sbutton"), "click", function(){
this.action = document.getElementById( "names" ).val() + ".ext";
});
If you were using a javascript library like jQuery, you could bind to the event handler like this:
$( "form[name=\"myInstitution\"]" ).on( "submit", function( e ){
var $this = $(this),
text = $this.find( "input#names" ).val();
$this.prop( "action", text + ".ext" );
});
$('#myForm').submit(function ()
{
var action = '';
// compute action here...
$(this).attr('action', action);
});
Hope it will help you..

How to maintain event observation after an element has been updated

I'm working on a project where I'd place an search box with a default set of results, over the layout using Prototype which is triggered from a click event.
When the output is set, that new page has it's own Javascript which is uses, to dynamically filter the results.
Now the new set of results do not work with the Javascript set previously.
How can I maintain a persistent event with calling new events each time?
Or is that what I am supposed to do.
Here is a bit of code which is loaded in 'loaded_page.php'
<script language="javascript">
var o = new Compass_Modal('add_button', 'history');
var placetabs = new Tabs('tabs', {
className: 'tab',
tabStyle: 'tab'
});
$$('.add_button').each(function(s, index){
$(s).observe('click', function(f) {
loadData();
});
});
function loadData() {
new Ajax.Request('/sponsors/search', {
onComplete: function(r) {
$('overlay').insert({
top:'<div id="search_table">'+r.responseText+'</div>'
});
}
})
}
</script>
Then in the included page which is inserted via javascript:
<div id="search_overlay">
<div id="form_box">
<img src="/images/closebox2.png" class="closebox" />
<form method="post" id="search_form" class="pageopt_left">
<input type="text" name="search_box" id="search_box" value="search" />
</form>
</div>
<div id="table_overlay">
<table class="sortable" id="nf_table" cellpadding="0" border="0" cellspacing="0">
<tr>
<th id="name_th">Name</th><th id="amount_th">Amount</th><th id="tax_letter_th">Tax Letter</th><th id="date_th">Date</th><th id="add_th">Add</th></tr>
<tr>
<td>Abramowitz Foundation (The Kenneth & Nira)</td><td><input type="text" name="amount" value="" id="amount_111" /></td><td><input type="checkbox" name="tax_letter" value="1" id="tax_letter_111" /></td><td><input type="text" name="date" value="" id="date_111" /></td><td><img src="/images/icons/add.png" title="add contact" /></td></tr>
... more rows
</table>
</div>
</div>
<script language="javascript">
var c = new Compass_Search('contacts', 'table_overlay');
c.set_url('/sponsors/sponsor_search');
$$('.add_button').each(function(s, index) {
$(s).observe('click', function(e) {
$(e).stop();
var params = $(s).href.split("/");
var userid = params[5];
var amount = 'amount_'+params[5];
var date = 'date_'+params[5];
var tax = 'tax_letter_'+params[5];
if(!Form.Element.present(amount) || !Form.Element.present(date)) {
alert('your amount or date field is empty ');
} else {
var add_params = {'amount':$F(amount), 'date':$F(date), 'tax':$F(tax), 'id':userid};
if(isNaN (add_params.amount)) {
alert('amount needs to be a number');
return false;
} else {
new Ajax.Request('/sponsors/add', {
method: 'post',
parameters: add_params,
onComplete: function(e) {
var post = e.responseText;
var line = 'amount_'+add_params.id;
$(line).up(1).remove();
}
})
}
}
});
});
this.close = $$('.closebox').each(function(s, index) {
$(s).observe('click', o.unloader.bindAsEventListener(this));
})
</script>
You'll notice in the inserted portion, a new Javascript which also, updated its own content with yet new observers. When the content gets updated, the observers do not work.
Use event delegation.
Besides making it possible to replace "observed" elements, this approach is also faster and more memory efficient.
document.observe('click', function(e){
var el = e.findElement('.add_button');
if (el) {
// stop event, optionally
e.stop();
// do stuff... `el` now references clicked element
loadData();
}
});
As you're calling Element#insert, I suppose String#evalScripts should be automatically called (as having looked in the implementation of those methods)
Maybe you can try to do some console.log()/alert() messages before the Element#observe calls, to see where it is going wrong. It may be because the Javascript is not evaluated at all, or that there is something wrong with your code or something like that.
As a tip: check the documentation on Array#invoke, with that method you can rewrite something like:
$$('.add_button').each(function(s, index){
$(s).observe('click', function(f) {
loadData();
});
});
into this:
$$('.add_button').invoke('observe', 'click', function(event){
loadData();
});
// $$('.add_button').invoke('observe', 'click', loadData);

Categories

Resources