I have an external JavaScript library to generate some formatted content. Let's call it ExternalLibrary.GenerateGutterDivs()
This code generates a table structure with some divs, something like:
<table>
<tr>
<td class="gutter">
<div>1</div>
<div>2</div>
<div>3</div>
...
</td>
<tr>
</table>
Once the table has been generate, I want to manipulate the generated DOM objects as follows:
<script type="text/javascript">
ExternalLibrary.generateGutterDivs();
alert("shomething"); //if I comment this I don't see the second alert
$("td.gutter > div").each(function(index, val)
{
alert("gutterfound");
});
</script>
The problem is that if I remove the first alert("something"), I don't see the second alert. This make think about the DOM maybe is not inmediatly refreshed. Do you know why I'm experiencing this situation?
Thanks in advanced.
This is a common issue. You should be returning a reference to the divs from MyCode.generateGutterDivs(), for example:
MyCode.generateGutterDivs = function () {
var safeReference = $("<div>1</div><div>2</div><div>3</div>")
.appendTo("td.gutter");
return safeReference;
};
Then:
<script type="text/javascript">
var divs = MyCode.generateGutterDivs();
divs.each(function(index, val)
{
alert("gutterfound"); // Should see 3 of these now
});
</script>
Edit: Since modifying the library is not an option for the poster, I think a setTimeout for 0 milliseconds will do the trick, yielding to the browser to finish updating the DOM:
<script type="text/javascript">
MyCode.generateGutterDivs();
setTimeout(function () {
divs.each(function(index, val)
{
alert("gutterfound"); // Should see 3 of these now
});
}, 0);
</script>
MyCode.GenerateGutterDivs() has not finished generating the DOM elements before the jQuery snippet is fired. You'll need to modify MyCode.GenerateGutterDivs() to accept a callback function, something akin to this:
MyCode.GenerateGutterDivs(function() {
$("td.gutter > div").each(function(index, val) {
alert("gutterfound");
});
});
//inside MyCode
GenerateGutterDivs = function(callback) {
// Generate formatted content.
callback();
};
Here's a proof of concept: http://jsfiddle.net/gnbNt/2/
Related
Would you please help me delay execution of my function until the content has loaded? I've streamlined my code to the essentials, bear with my typos:
function Phase1()
{
$(".Hidden").load("hidden.html");
$(window).load(Phase2());
/* I've also tried $(document).ready(Phase2()); */
/* and $(."Hidden").load("hidden.html",Phase2()); */
/* and window.onload... */
}
function Phase2()
{
var Loop;
var Source_Array = document.getElementsByClassName("Random");
for (Loop=0;Loop<Source_Array.length,Loop++)
{ alert(Source_Array[Loop].innerHTML; };
}
The Random class contains several items. On the first pass the alerts are never called (length is 0), on the 2nd iteration it's had time to load everything.
I see no errors in the console when executing.
I have a small and neat solution for your problem, all you need to do is,
Call a setInterval for very short span to check the element is present in DOM or not, if its not your interval will go on, once the element is present, trigger your functions and clear that interval.
code will look like this..
var storeTimeInterval = setInterval(function() {
if (jQuery('.yourClass').length > 0) {
//do your stuff here..... and then clear the interval in next line
clearInterval(storeTimeInterval);
}
}, 100);
The page will load the elements from top to bottom.
If you want your JS code to execute after all elements have loaded, you may try any of the following:
Move your script to the bottom of the page.
<html>
<head></head>
<body>
<!-- Your HTML elements here -->
<script>
// Declaring your functions
function Phase1()
{
$(".Hidden").load("hidden.html");
}
function Phase2()
{
var Loop;
var Source_Array = document.getElementsByClassName("Random");
for (Loop=0;Loop<Source_Array.length,Loop++)
{ alert(Source_Array[Loop].innerHTML; };
}
// Executing your functions in that order.
Phase1();
Phase2();
</script>
</body>
</html>
Bind your functions to document ready using Vanilla JS.
document.addEventListener("DOMContentLoaded", function() {
Phase1();
Phase2();
});
Bind your functions to document using jQuery.
$(document).ready(function() {
Phase1();
Phase2();
});
I have two buttons: one with class btn-star, and the other with btn-current. I am calling an independent function on each of their clicks. But now, I want to call only one function when they are called.
My code is similar to this:
$('document').ready(() => {
$(document).on('click', '.btn-star', function () {
// Do stuff
}
$(document).on('click', '.btn-current', function () {
// Do stuff
}
}
You can try this code. You can use multiple elements click event for one action with only one line code, Just use a comma for separating elements
$('document').ready(() => {
const myFunction= () => {
// Your Code here...
}
$(document).on('click', '.btn-current, .btn-current', function () {
myFunction();
}
}
You can define a function separately and pass it in as callback for both buttons' on click handler. For example -
$('document').ready(() => {
const commonFunc = () => {
// do common stuffs here
}
$(document).on('click', '.btn-star', commonFunc());
$(document).on('click', '.btn-current', commonFunc());
}
Hope that helps!
If you want to call the same function you can select your two button classes, using a simple j-query expression:
$('.btn-star, .btn-current').click(function() {
// Do stuff
}
Ad your selectors separated by a comma, inside the quotation marks.
You can read more about j-query selector at this link:
https://www.sitepoint.com/comprehensive-jquery-selectors/
A little shorter code...
$('document').ready(() => {
function commonFunc() {
//do stuffs here
}
$('.btn-star, .btn-current').on('click', commonFunc);
}
you can try like this:
function test()
{
//your code
}
$(".btn1, .btn2").on("click", funciton(){
test();
});
Try below code
$('.btn-star, .btn-current').on('click', function () {
// Do shared stuff
});
Reference: http://api.jquery.com/on/
Why is [Javascript] tagged on this post? If it is meant to be there, I'm assuming you are going to accept javascript responses right?
If you're going javascript, it is much easier, and you can just add a onClick='function()' to your html code and do your functions in there.
<html>
<head>
<script>
function buttonFunction(buttonName){
//EDIT 3.0: You can make one button do the same as the other button, but you can also make it do something else at the same time!
if(buttonName == 'btn-star'){
//other code such as:
alert("Stars are awesome!");
}
alert("You just clicked " + buttonName);
}
</script>
</head>
<body>
<div id='button1'>
<button id='btn-star' onclick='buttonFunction("btn-star")'>btn-star</button>
</div>
<br/>
<div id='button2'>
<button id='btc-current' onclick='buttonFunction("btn-current")'>btn-current</button>
</div>
</body>
</html>
If you want, you can also additionally make one button do the same as the other, and then after that do something different like I did in this snippet.
P.S: I'm just assuming javascript is allowed, because after all, it is tagged on this post.
EDIT: I showed you an example of one button doing slightly differently then the other, but still the same in a way
ANOTHER EDIT: You can do a lot of stuff with this, added ideas on what else you could do with this snippet.
You can try
$('.btn-star , .btn-current').on('click', function () {
//do something common for elements
});
I'm generating some HTML at runtime and I'm wondering how to make a plugin work on the newly created HTML. I've got something that looks llike this:
<input type="text" class="SomeClass">
<div id="Test"></div>
<script>
function Start() {
setTimeout(function () {
$('#Test').html('<input type="text" class="SomeClass">');
}, 1000);
}
$(".SomeClass").SomePlugin();
$(Start);
</script>
The input element has all the functionalities of the plugin but when I add the HTML inside the Test div the input element inside there doesn't work as expected. How can I use the plugin on dynamically generated HTML?
For plugin to work with new created elements, you need to init the plugin on those elements for it to work. There are several ways to do this, such as calling it again when new elements are added.
If you just want to avoid changing your code and adding that, you could override jquery html to check if you are adding an element with SomeClass and call the plugin for it automatically:
(function($)
{
var oldhtml = $.fn.html; //store old function
$.fn.html = function() //override html function
{
var ret = oldhtml.apply(this, arguments); // apply jquery html
if(arguments.length){
if(ret.find(".SomeClass").length){
ret.find(".SomeClass").SomePlugin(); // call plugin if the html included an element with .SomeClass
}
}
return ret;
};
})(jQuery);
$.fn.SomePlugin = function() {
$("body").append("plugin activated <br/>");
}
function Start() {
setTimeout(function() {
$('#Test').html('<input type="text" class="SomeClass">');
$('#Test').html()
}, 1000);
}
$(".SomeClass").SomePlugin();
$(Start);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="SomeClass">
<div id="Test"></div>
I opted for a solution that used jQuery promises. Here is the Fiddle
The HTML (basic copy of yours):
<input type="text" class="SomeClass">
<div id="Test"></div>
The Javascript:
$.fn.SomePlugin = function(){
$(this).val("plugin activated");
}
function Start() {
alert('hi from start');
$('#Test').html('<input type="text" class="SomeClass">');
return $.when();
}
$(document).ready(function(){
Start().then(function () {
alert('hi from done');
$(".SomeClass").SomePlugin();
});
});
I had some issue with the $(Start) so i opted for the document.ready approach. The only real difference is that Start returns $.when (SO Post Here) and I chain a 'then' after the call to start. This allows the page to setup and then you can run any plugins that you want and ensure that the required elements are in the DOM before the plugin attempts to manipulate them.
So I know this question has been asked many times but I can't seem to get this working, even though it looks correct to me. My jquery functions from an external file aren't loading properly.
My tableMethods.js external file looks like
$(function(){
// Write FITS
function writeFits(){
var data = $('.sastable').bootstrapTable('getData');
var name = $('#fitsname').val();
$.getJSON($SCRIPT_ROOT + '/writeFits', {'data':JSON.stringify(data),'name':name},
function(data){
$('#fitsout').text(data.result);
});
}
// Delete rows from data table
function deleteRows(){
var $table = $('.sastable');
var $delete = $('#delete');
var ids = $.map($table.bootstrapTable('getSelections'), function (row) {
return row.id
});
$table.bootstrapTable('remove', {
field: 'id',
values: ids
});
}
})
My html header looks like
<script type="text/javascript" src="/static/js/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="/static/js/bootstrap.min.js"></script>
<script type="text/javascript" src="/static/js/bootstrap-table.js"></script>
<script type='text/javascript' src="/static/js/tableMethods.js"></script>
When I check the inspector, it says the file has loaded yet when I click my button that looks like
<button id="delete" class="btn btn-danger" type='button' onClick='deleteRows()'>Delete Rows</button>
I get the error
Uncaught ReferenceError: deleteRows is not defined
This is a scoping problem. You have to move your functions outside of $(function() { ... })
In JavaScript, anything exclusively defined within a function, generally stays within a function:
var x = 3;
(function() {
var y = 1;
})();
console.log(x); // 3
console.log(y); // error
So if you’re defining a function within a function, you can only invoke it from that function you have defined it in. When trying to invoke it from anywhere else, the inner function will seem undefined.
In your case, you can simply remove the wrapper function:
$(function() { // Delete this...
...
}); // And this
For more information, read You Don’t Know JS: Scope & Closures
I'm trying to learn some jQuery, and I setup a test page with the following code:
<a id='encode' href='javascript: void(0)'>encode</a> |
<a id='decode' href='javascript: void(0)'>decode</a> |
<br/>
<textarea id='randomString' cols='100' rows='5'></textarea>
<script type='text/javascript'>
$(document.ready(function () {
$('#encode').click(function() {
$('#randomString').val(escape($('#randomString').val()));
});
$('#decode').click(function() {
$('#randomString').val(unescape($('#randomString').val()));
});
});
</script>
The idea is I can put something in the textarea and click either "encode" or "decode", and it will either escape or unescape what I put into the textarea.
This code works just fine, but my question has to do with how I am changing the value of the textarea. In my code, I am selecting the textarea value twice: once to (un)escape it, and once again to change the value. IMO this seems clunky and maybe unnecessary. I thought maybe I could do something like this instead:
$('#randomString').val(escape(this));
But this seems to refer to the object of the link I clicked, not the #randomString selector, so is there some other magic word I can use to reference that $('#randomString')?
$('#randomString').val(escape(this));
This does not get the object you want. It is effectively the equivalent of doing this:
var foo = escape(this);
$('#randomString').val(foo);
this only means something different when you start a new scope with a function definition.
jQuery does offer this kind of functionality with a callback option:
$('#randomString').val(function (idx, oldVal) {
return escape(oldVal);
});
The second parameter is the current value of the element; the return value sets a new value for the element.
You can try this
$(document.ready(function () {
$('#encode').click(function() {
var $randomString = $('#randomString');
$randomString.val(escape($randomString.val()));
});
$('#decode').click(function() {
var $randomString = $('#randomString');
$randomString.val(unescape($randomString.val()));
});
});
The short answer, if I understand you correctly, is no. There isn't a way to refer to $('#randomString') where you're talking about. It's just a parameter to the val method, so it's just plain JavaScript syntax, no jQuery "magic".
To accomplish the task at hand and make the code cleaner and less clunky, I would save off the jQuery object for #randomString so you don't have to keep creating it:
$(document.ready(function () {
var $rndStr = $('#randomString');
$('#encode').click(function() {
$rndStr.val(escape($rndStr.val()));
});
$('#decode').click(function() {
$('#rndStr').val(unescape($rndStr.val()));
});
});
You could make it a little generic:
$.fn.applyVal = function(func) {
return this.each(function() {
$(this).val( func( $(this).val() ) );
});
};
Then the following call is enough:
$('#randomString').applyVal(escape);