Separating JS to multiple files - javascript

There are multiple pages on my web-project working with exactly same JS functions. I was copying and pasting same functions to all pages' js files. But recently seperated common functions to another js file named common_fns.js, for every page created just selector cached variables and placed at the top of every page in order some_page.js, common_fns.js . Something like that
some_page.js
$(function() {
var closer=$("#nlfcClose"),
NewFormContainer=$("#NewLessonFormContainer"),
opener=$("#nlfcOpen"),
NewForm=$("#NewLessonForm"),
OpsForm=$("#LessonOps"),
SelectBox=$( "#courses" ),
SelectBoxOptions=$("#courses option"),
jquiBtn=$(".jquiBtn"),
AddOp="AddLesson",
DelOp="DelLesson";
});
common_fns.js
$(function() {
SelectBoxOptions.text(function(i, text) {
return $.trim(text);
});
SelectBox.combobox();
jquiBtn.button();
closer.button({
icons: {
primary: "ui-icon-closethick"
},
text: false
}).click(function(){
NewFormContainer.slideUp("slow");
});
opener.click(function(){
NewFormContainer.slideDown("slow");
});
NewForm.submit(function(){
var querystring = $(this).serialize();
ajaxSend(querystring, AddOp);
return false;
});
OpsForm.submit(function(){
var querystring = $(this).serialize();
ajaxSend(querystring, DelOp);
return false;
});
});
It was working when I copied and pasted common functions to every pages' file. But now it doesn't: Firebug shows error message undefined SelectBoxOptions even for first function. What am I missing? Only way to copy-paste same functions into every pages' js file?

You are declaring local variables inside the event handler, that's why you can't use them in the next event handler.
Declare the variables outside the function:
var closer, NewFormContainer, opener, NewForm, OpsForm, SelectBox, SelectBoxOptions, jquiBtn, AddOp, DelOp;
$(function() {
closer = $("#nlfcClose");
NewFormContainer = $("#NewLessonFormContainer");
opener = $("#nlfcOpen");
NewForm = $("#NewLessonForm");
OpsForm = $("#LessonOps");
SelectBox = $( "#courses" );
SelectBoxOptions = $("#courses option");
jquiBtn = $(".jquiBtn");
AddOp = "AddLesson";
DelOp = "DelLesson";
});

Related

JS Variable Not Being Passed Correctly

I've been working on this code for a while. I have a HTML, JS and a Code.js page.
On changing of the value in a Dropdown list on my HTML form, the item in the Dropdown is passed to the Code.js to have the result returned, however, I keep having NULL as my result. -arr is the result.
Another issue, is that I can see in the script logs that getRowData() is being executed twice, not sure why, but this may be overwriting our array.
HTML
JS
//$('#searchDropdown').one('change', function(){
//$("#searchDropdown").change(function(){
//$('#searchDropdown').on('keyup propertychange change', function(){
//$('#searchDropdown').on('input', function(){
//$('#searchDropdown').one('submit', function(){
$('#searchDropdown').one('change', function(){
var selatr = $('#input1').val();
google.script.run.withSuccessHandler(poperr).getRowData(selatr);
});
function poperr(arr){
alert(arr +" ! ");
}
Code.GS
function getRowData(selatr){
//Vlookup a GoogleSheet and return the resulting row
sheet_data.getRange(2,16).setValue(selatr); //set for vlookup
var x = sheet_data.getRange(3,16).getValues();
var arr= [];
arr.push({
id : selatr
name : sheet_data.getRange(x,2).getValues()
})
return arr;
}
It might be because you have multiple event handlers in your code and your getRowData function is being called twice.
Try e.stopImmediatePropagation(); This stops the rest of the event handlers from being executed.
$('#searchDropdown').one('change', function(e){
e.stopImmediatePropagation();
var selatr = $('#input1').val();
google.script.run.withSuccessHandler(poperr).getRowData(selatr);
});

Jquery .change() event fires only once

So I'm fairly novice with jquery and js, so I apologise if this is a stupid error but after researching I can't figure it out.
So I have a list of data loaded initially in a template, one part of which is a dropdown box that lets you filter the data. My issue is that the filtering only works once? As in, the .change function inside $(document).ready() only fires the once.
There are two ways to reload the data, either click the logo and reload it all, or use the search bar. Doing either of these at any time also means the .change function never fires again. Not until you refresh the page.
var list_template, article_template, modal_template;
var current_article = list.heroes[0];
function showTemplate(template, data)
{
var html = template(data);
$("#content").html(html);
}
$(document).ready(function()
{
var source = $("#list-template").html();
list_template = Handlebars.compile(source);
source = $("#article-template").html();
article_template = Handlebars.compile(source);
source = $("#modal-template").html();
modal_template = Handlebars.compile(source);
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
$("#classFilter").change(function()
{
console.log("WOW!");
var classToFilter = this.value;
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.heroClass.search(classToFilter) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
$("#searchbox").keypress(function (e)
{
if(e.which == 13)
{
var rawSearchText = $('#searchbox').val();
var search_text = rawSearchText.toLowerCase();
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.name.search(search_text) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
}
});
$("#logo").click(function()
{
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
//$("#logo").click();
});
function displayModal(event)
{
var imageNumber = $(this).data("id");
console.log(imageNumber);
var html = modal_template(current_article.article[0].vicPose[imageNumber]);
$('#modal-container').html(html);
$("#imageModal").modal('show');
}
I should note two things: first, that the search bar works perfectly, and the anonymous function inside both of them is nearly identical, and like I said, the filtering works perfectly if you try it after the initial load. The second is that the same problem occurs replacing .change(anonymous function) with .on("change",anonymous function)
Any help or advice would be greatly appreciated. Thanks.
I agree with Fernando Urban's answer, but it doesn't actually explain what's going on.
You've created a handler attached to an HTML element (id="classFilter") which causes part of the HTML to be rewritten. I suspect that the handler overwrites the HTML which contains the element with the handler on it. So after this the user is clicking on a new HTML element, which looks like the old one but doesn't have a handler.
There are two ways round this. You could add code inside the handler which adds the handler to the new element which has just been created. In this case, that would mean making the handler a named function which refers to itself. Or (the easier way) you could do what Fernando did. If you do this, the event handler is attached to the body, but it only responds to clicks on the #classFilter element inside the body. In other words, when the user clicks anywhere on the body, jQuery checks whether the click happened on a body #classFilter element. This way, it doesn't matter whether the #classFilter existed when the handler was set. See "Direct and delegated events" in jQuery docs for .on method.
Try to use some reference like 'body' in the event listeners inside your DOM like:
$('body').on('click','.articleButton', function() {
//Do your stuff...
})
$('body').on('click','#classFilter', function() {
//Do your stuff...
})
$('body').on('keypress','#searchbox', function() {
//Do your stuff...
})
$('body').on('click','#logo', function() {
//Do your stuff...
})
This will work that you can fire it more than once.

jQuery getting text content of a span

I am trying to write a delete function in Dropzone.js. In order to do that I need the id of the file the way it was uploaded.
I tried to get a property of an object with no success. Now I am trying to use jQuery to get the value or text content of the span that has it.
this is the screenshot of the structure. The jQuery code I am trying is:
var loooot = $(".dz-filename").parents('span').text();
To be more specific I am trying to get the number 1_1477778745352 (which is a time stamp).
The Dropzone code is as follows:
<script>
var listing_id = "1";
// these are the setting for the image upload
Dropzone.options.pud = {
acceptedFiles: ".jpeg,.jpg,.png,.gif",
uploadMultiple: false,
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 1, // MB
addRemoveLinks: true,
maxFiles: 10,
renameFilename: function (filename) {return listing_id + '_' + new Date().getTime();},
init: function()
{
this.on("removedfile", function(file)
{
var loooot = $("span", ".dz-filename").html();
alert(loooot);
});
}
};
</script>
Try this use JQuery's .text(); to get inner text
Update: use this with DOM .ready() like that.
Deep selector
$(document).ready(function(){
var fname = $("#pud .dz-filename span [data-dz-name]").text();
});
OR (if your form is dynamic)
function get_fname(){
return $("#pud .dz-filename span [data-dz-name]").text();
}
Then use get_fname();
It becomes undefined because dropzone works dynamicly, use this:
$('body').find(".dz-filename").find('span').text();
Best way to do this is to declare dropzone:
//first declare somewhere variable
var my_drop;
// then on creating dropzone:
my_drop = new Dropzone('.dropzone', {
/* your setup of dropzone */
});
Then you can retreive information about files with this:
my_drop.files[0].name
The [0] represent's first file, you can loop through them if there's more then one.
Use:
var loooot = $("span", ".dz-filename").html();
Working Demo.
var loooot = $("span", ".dz-filename").html();
alert(loooot);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="dz-filename">
<span>Test</span>
</div>
EDIT
Since you are setting the text dynamically it may happens that jquery read the HTML before that you set it, to prevent this you have to call this function after the timestamp as a callback (i can't help you without seeing how you set the span text).
So do something like:
function setSpan(callback) {
// Set your stuffs
// Call the callback
callback();
}
function getText() {
// I'm the callback witch get the html
}
//Onload
setSpan(getText());
EDIT
For dropzone you can use queuecomplete that start a function after the queue, i'm not an dropzone expert but i suppose:
init: function () {
this.on("queuecomplete", function (file) {
//Get span html
alert("All files have uploaded ");
});
}
The working solution I found is this:
init: function()
{
this.on("removedfile", function(file)
{
var loooot = $(file.previewElement).find('[data-dz-name]').text();
alert(loooot);
});
}

Handling State changes jQuery and History.js

Ok, so I need some insight into working with History.js and jQuery.
I have it set up and working (just not quite as you'd expect).
What I have is as follows:
$(function() {
var History = window.History;
if ( !History.enabled ) {
return false;
}
// Capture all the links to push their url to the history stack and trigger the StateChange Event
$('.ajax-link').click(function(e) {
e.preventDefault();
var url = this.href; //Tells us which page to load
var id = $(this).data('passid'); //Pass ID -- the ID in which to save in our state object
e.preventDefault();
console.log('url: '+url+' id:'+id);
History.pushState({ 'passid' : id }, $(this).text(), url);
});
History.Adapter.bind(window, 'statechange', function() {
console.log('state changed');
var State = History.getState(),
id = State.data.editid; //the ID passed, if available
$.get(State.url,
{ id: State.data.passid },
function(response) {
$('#subContent').fadeOut(200, function(){
var newContent = $(response).find('#subContent').html();
$('#subContent').html(newContent);
var scripts = $('script');
scripts.each(function(i) {
jQuery.globalEval($(this).text());
});
$('#subContent').fadeIn(200);
});
});
});
}); //end dom ready
It works as you'd expect as far as changing the url, passing the ID, changing the content. My question is this:
If I press back/forward on my browser a couple times the subContent section will basically fadeIn/fadeOut multiple times.
Any insight is appreciated. Thanks
===================================================
Edit: The problem was in my calling all of my <script> and Eval them on each statechange. By adding a class="no-reload" to the history controlling script tag I was able to do:
var scripts = $('script').not('.no-reload');
This got rid of the problem and it now works as intended. Figure I will leave this here in case anyone else runs into the same issue as I did.
The problem was in my calling of all of my <script> and Eval them on each statechange. By adding a class="no-reload" to the history controlling script tag I was able to do:
var scripts = $('script').not('.no-reload');
This got rid of the problem and it now works as intended. Figure I will leave this here in case anyone else runs into the same issue as I did.

Event object eaten by jQuery animation callback

I have a problem with event object passed to the function in drop event. In my code, div#dropArea has it's drop event handled by firstDrop function which does some animations and then calls the proper function dropFromDesktop which handles the e.dataTransfer.files object. I need this approach in two separate functions because the latter is also used further by some other divs in the HTML document (no need to duplicate the code). First one is used only once, to hide some 'welcome' texts.
Generally, this mechanism lets you drag files from desktop and drop them into an area on my website.
Here's, how it looks (in a shortcut):
function firstDrop(ev) {
var $this = $(this);
//when I call the function here, it passes the event with files inside it
//dropFromDesktop.call($this, ev);
$this.children('.welcomeText').animate({
opacity: '0',
height: '0'
}, 700, function() {
$('#raw .menu').first().slideDown('fast', function() {
//when I call the function here, it passes the event, but 'files' object is empty
dropFromDesktop.call($this, ev);
});
});
}
function dropFromDesktop(ev) {
var files = ev.originalEvent.dataTransfer.files;
(...) //handling the files
}
$('#dropArea').one('drop', firstDrop);
$('some_other_div').on('drop', dropFromDesktop);
The problem is somewhere in jQuery.animation's callback - when I call my function inside it, the event object is passed correctly, but files object from dataTransfer is empty!
Whole script is put inside $(document).ready(function() { ... }); so the order of function declarations doesn't matter, I guess.
I suspect your problem is related with the lifetime of the Event object. Unfortunately, I have no clue about the cause of it. But, there is a way to workaround it that I can think of and it is keeping a reference to Event.dataTransfer.files instead.
var handleFileList = function(fn) {
return function(evt) {
evt.preventDefault();
return fn.call(this, evt.originalEvent.dataTransfer.files);
};
};
var firstDrop = function(fileList) { ... }
var dropFromDesktop = function(fileList) { ... }
$('#dropArea').one('drop', handleFileList(firstDrop));
$('some_other_div').on('drop', handleFileList(dropFromDesktop));​

Categories

Resources