I have this code
;(function($, document, window) {
'use strict';
var defaults = {
el: '.na',
};
$.fn.baboy = function( options ) {
var settings = $.extend( {}, defaults, options );
this.each(function(){
var dis = $(this);
$('body').on('click', dis, function(e) {
var text = dis.text();
$( settings.el ).append('Click ' + text + '</br>' );
});
});
};
})(jQuery, document, window);
Then I wanted to use it on two elements
Button 1
<p class="duh"></p>
Button 2
<p class="duh2"></p>
using the function in two elements
$('.btn').baboy({
el: '.duh',
});
$('.btn2').baboy({
el: '.duh2',
});
However, everytime I click any of the a tag, it seems like the other one also runs.
Here the fiddle to see the issue https://jsfiddle.net/xpvt214o/100340/
The issue is because you're using a jQuery object in the selector argument of the delegated on() call. Quite why this then affects all elements not the bound one I'm not sure without digging in to the jQuery source. However I can say that your usage is incorrect; that argument should be a string.
That said, you don't need a delegated event handler at all. You don't need the each() either. You can create the click() event handler on the element(s) the plugin was instantiated on, like this:
;(function($, document, window) {
'use strict';
var defaults = {
el: '.na',
};
$.fn.baboy = function(options) {
var settings = $.extend({}, defaults, options);
return this.on('click', function() {
$(settings.el).append('Click ' + $(this).text() + '</br>');
});
};
})(jQuery, document, window);
$('.btn').baboy({
el: '.duh',
});
$('.btn2').baboy({
el: '.duh2',
});
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
color: #fff;
}
a {
display: inline-block;
background: #a3de14;
padding: 10px 30px;
font-size: 12px;
text-decoration: none;
}
.duh,
.duh2 {
background: #fff;
padding: 10px 20px;
color: #222;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Button 1
<p class="duh"></p>
Button 2
<p class="duh2"></p>
You should also note that this plugin is massive overkill, as the logic for all button instances can be distilled in to a single event handler with 3 lines of code. However I'm going to assume this is just a learning exercise.
Related
I am using the FoundationPress theme (Wordpress Theme with the Foundation 6 from Zurb framework), and i'd like to ajaxify it. (using Ajaxify Wordpress Site plugin).
Now my problem is that most of the javascript that's on my website isn't working after an ajax load.
I have found that this is because most of the javascript in the foundation.js file is executed on document.ready, and that this event is not being triggered when loading a page with ajax.
I understand that it is not possible to trigger the document.ready event after page load. And after seeing multiple threads here, it appears the only solution is to create a new function with the code that's needed on document.ready and ajaxComplete.
BUT, Foundation has a lot of javascript files, and most of it is above my level of understanding. Is there any way to create a function that would automate this ?
EDIT I tried this. I need to pass jQuery as an argument or the code inside initialiseSticky will not work. It works for document.ready but not for ajaxComplete, any idea ?
jQuery(function($) {
console.log('document ready- sticky');
initialiseSticky($);
});
$(document).ajaxComplete(function ($) {
console.log('ajax complete- sticky');
initialiseSticky($);
}(jQuery));
function initialiseSticky($) {
//my code
}
Not sure about foundation.js but if you can make a variable, FooBar for example, assign the function() in $(document).ready() to that variable, and then on ajaxComplete call the variable/function again to "re-trigger" it, like below:
jsFiddle
var res = $('#result'),
bg = $('#bg-div'),
btn = $('#btnTest'),
i = 0, // just for demo to illustrate that it is changing
FooBar;
$(document).ready(FooBar = function() {
bg.delay(200).fadeIn(2000);
console.log('document is ready ' + i++);
});
// simulate ajaxComplete
btn.on('click', function() {
res.text('just dummy text here ' + i);
bg.fadeOut(500);
FooBar();
});
body { margin: 0; padding: 0 }
#bg-div { background-color: orange; width: 100%; height: 100%; position: fixed; z-index: -1; display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="bg-div"></div>
<button id="btnTest">Click Me</button>
<div id="result"></div>
I have this code:
document.getElementById('auth-button').addEventListener('click', authorize);
When my page load I want to trigger that without clicking the button.
This is my view
When authorized button clicked this is the output
I want to auto click that button when my page load.
You can use addEventListener to the DOMContentLoaded event:
document.addEventListener('DOMContentLoaded', function() {
authButton.click();
}, false);
Full example:
https://jsfiddle.net/7q0gxehk/1/
you can use Document ready in jQuery, try this..
$( document ).ready(function() {
authorize();
});
or this in javaScript..
window.onload = authorize;
NOTE: The load event fires at the end of the document loading process. At this point, all of the objects in the document are in the DOM, and all the images, scripts, links and sub-frames have finished loading.
You could call the function authorize() on load of page using below code :
document.addEventListener("DOMContentLoaded", function(event) {
authorize();
});
You can register authorize as handler to be called when the page is fully loaded:
$(document).ready(authorize);
This requires jQuery. The same can be achieved without jQuery this way:
window.addEventListener('load', authorize);
It would be easier to tigger authorize function directly on page load using window.onload which is better than document.onload, see window.onload vs document.onload
window.onload = authorize;
However, if you are thinking about triggering click programmatically which is not suggested since it won't work properly across browsers e.g. Safari doesn't work at all
None of the other answers offered thus far seem to take something into account - that the registered handler may in fact need to be aware of it's place in the DOM.
We could for instance, have a number of buttons that all call the same handler, with that handler manipulating the surrounding DOM. Simply calling authorize when the page loads will not be sufficient.
I've chosen to use DIVs instead of BUTTONs to demonstrate that the .click() method still works.
A far better way is to actually click the button, using javascript.
#1 Not working
function byId(id){return document.getElementById(id)}
function allByClass(clss){return document.getElementsByClassName(clss)}
// useful for HtmlCollection, NodeList, String types
function forEach(array, callback, scope){for (var i=0,n=array.length; i<n; i++)callback.call(scope, array[i], i, array);} // passes back stuff we need
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
forEach(allByClass('mBtn'), addHandler);
function addHandler(elem)
{
elem.addEventListener('click', authorize, false);
}
alert('hit a okay to call authorize');
authorize(); // wont return from this call, since authorize relies on a valid 'this' value
}
function authorize(evt)
{
this.classList.add('clicked');
this.textContent = 'clicked';
}
.mBtn
{
border: solid 1px #555;
border-radius: 2px;
display: inline-block;
}
.clicked
{
color: #dddddd;
pointer-events: none;
}
<div class='mBtn'>Try me</div><div id='btn2' class='mBtn'>Or me</div><div class='mBtn'>Or even, me</div>
#2 - Does work
function byId(id){return document.getElementById(id)}
function allByClass(clss){return document.getElementsByClassName(clss)}
// useful for HtmlCollection, NodeList, String types
function forEach(array, callback, scope){for (var i=0,n=array.length; i<n; i++)callback.call(scope, array[i], i, array);} // passes back stuff we need
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
forEach(allByClass('mBtn'), addHandler);
function addHandler(elem)
{
elem.addEventListener('click', authorize, false);
}
alert('hit okay to click the 2nd button with javascript');
byId('btn2').click(); // will return from this call, since authorize relies on a valid 'this' value, and the btn gives it one.
}
function authorize(evt)
{
this.classList.add('clicked');
this.textContent = 'clicked';
}
.mBtn
{
border: solid 1px #555;
border-radius: 2px;
display: inline-block;
}
.clicked
{
color: #dddddd;
pointer-events: none;
}
<div class='mBtn'>Try me</div><div id='btn2' class='mBtn'>Or me</div><div class='mBtn'>Or even, me</div>
Use one of the following:
<body onload="script();">
or
document.onload = function ...
or
window.onload = function ...
After some hard work on the backend of my Web Application I noticed that the GetMeasure Request takes up to 10 seconds to finish. I decided to apply an overlay so a potential user won't get confused because nothing happens on the screen. No matter if the request is successfull or not the overlay should get removed after the call - so using the complete handler should be the best choice - at least I thought. I really don't get why but in opposite to the success handler the complete handler won't get called.
AJAX Request:
$_loadingCircle = $('<img id="loading" src="http://www.obergurgl.com/_images/layout/loading.gif"/>');
PopulateOverlay($_loadingCircle);
$.ajax({
url: 'CoDTracker/Home/GetMeasures',
type: 'POST',
dataType: "html",
data: {
buID: buid,
aID: aid,
lID: lid
},
success: function (data) {
$('#measures').html(data);
},
complete: function () {
$_overlay.remove();
}
});
The request ends with status 200 (successfull) but the overlay won't get removed. I'm sure that the request completed because my measures got filled into the page while the circle spins as crazy instead of disappearing.
Am I doing something wrong?
Edit:
Overlay-definition
function PopulateOverlay($content) {
$_overlay = $('<div class="overlay">');
$content.appendTo($_overlay);
$_overlay.appendTo('body');
}
Your $_overlay is defined incorrectly.
Please use:
$_overlay = $('div.overlay');
And please refer to jQuery Selectors for more information:
https://api.jquery.com/category/selectors/
The way to select a div with a particular class, is not to copy the entire <div class="">, but rather as I did in the example above.
EDIT: in fact, if you make this change, your PopulateOverlay will no longer work, so you should rather just select it without assigning it to a variable:
complete: function () {
$('div.overlay').remove();
}
Because overlay is appended in the DOM, you should remove it with .class:
complete: function () {
$('.overlay').remove();
}
First, if there's no error, and that's all your code, it should work fine.
Let's try to make an example, with a mimic function to mimic the behavior of ajax complete, we can write it like:
var $_overlay = null; // We assume you define it somewhere, and it's visible to all your functions.
function PopulateOverlay($content) {
$_overlay = $('<div class="overlay">');
$content.appendTo($_overlay);
$_overlay.appendTo('body');
}
// See this as an ajax call with 2 sec delay.
function mimic(cb) {
setTimeout(cb, 2000);
}
function theWorks() {
$someEle = $('<div class="example">example</div>');
PopulateOverlay($someEle);
mimic(function() {
$_overlay.remove();
});
}
$(function() {
theWorks();
});
.overlay {
display: block;
width: 100px;
height: 100px;
background-color: black;
}
.example {
color: cyan;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
So I guess, that your codes, is inside another function, and you may call it many times, let's make a button, and click to trigger it:
var $_overlay = null; // We assume you define it somewhere, and it's visible to all your functions.
function PopulateOverlay($content) {
$_overlay = $('<div class="overlay">');
$content.appendTo($_overlay);
$_overlay.appendTo('body');
}
// See this as an ajax call with 2 sec delay.
function mimic(cb) {
setTimeout(cb, 2000);
}
function theWorks() {
$someEle = $('<div class="example">example</div>');
PopulateOverlay($someEle);
mimic(function() {
debugger;
$_overlay.remove();
});
}
$(function() {
$('#click').on('click', theWorks);
});
.overlay {
display: block;
width: 100px;
height: 100px;
background-color: black;
}
.example {
color: cyan;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="click">Click</button>
Now, if click the button before the previous pop out disappear, some popouts last forever.
Why? Because when you click again, your $_overlay will be assign to a newly created element, which means you lost the reference to the previous pop out, and when later the remove works takes action, it only remove the newest one, and all the following removes, are about to remove something that is not on the page, so you won't see effects, and older popouts remains.
We could fix it, by catch the current element in another variable when you're executing your codes. This would work if you expect many pop outs.
var $_overlay = null; // We assume you define it somewhere, and it's visible to all your functions.
function PopulateOverlay($content) {
$_overlay = $('<div class="overlay">');
$content.appendTo($_overlay);
$_overlay.appendTo('body');
}
// See this as an ajax call with 2 sec delay.
function mimic(cb) {
setTimeout(cb, 2000);
}
function theWorks() {
$someEle = $('<div class="example">example</div>');
PopulateOverlay($someEle);
// Cache the current overlay, or simply move $_overlay here, if no other using it.
var $_curOverlay = $_overlay;
mimic(function() {
$_curOverlay.remove();
});
}
$(function() {
$('#click').on('click', theWorks);
});
.overlay {
display: block;
width: 100px;
height: 100px;
background-color: black;
}
.example {
color: cyan;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="click">Click</button>
Or as what Laurens Swart suggest, simply toggle the state if you only need one pop out at a time.
var $_overlay = $('.overlay');
function PopulateOverlay($content) {
$_overlay
.empty() // Clear previous
.append($content) // Append the content
.show(); // Make it visible.
}
// See this as an ajax call with 2 sec delay.
function mimic(cb) {
setTimeout(cb, 2000);
}
function theWorks() {
$someEle = $('<div class="example">example</div>');
PopulateOverlay($someEle);
mimic(function() {
$_overlay.hide(); // Instead of remove, we make it hide, so we can reuse it later.
});
}
$(function() {
$('#click').on('click', theWorks);
});
.overlay {
display: none;
width: 100px;
height: 100px;
background-color: black;
}
.example {
color: cyan;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="click">Click</button>
<div class="overlay"></div>
I defined an object with properties and methods. But I can't find how to attach a jQuery function to a method. What I want is : when I click on the object #myTarget change its html text.
I wrote this :
function blockTest(word){
this.word = ""+genRandInt(0, 25);
this.applyNewWord = function(){
$(document).ready(function(){
$("#myTarget").click(function(){
$("#myTarget").html(this.word);
});
});
};
}
Actually, I'm trying to
Accomplishing what you want based on the code you provided isn't the way to go. I'd first create an Object rather than using a function. Insert your attributes inside that object and handle your DOM events separately:
(function($) {
var obj = {
word: "Example Word",
applyNewWord: function() {
return this.word;
}
}
$(function() {
$("#myTarget").on("click", function() {
$(this).text(obj.applyNewWord())
});
});
}(jQuery));
div {
border: 1px solid black;
cursor: pointer;
padding: 5px;
}
<div id="myTarget">Dummy Text</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
function blockTest(word){
var self = this;
self.word = ""+genRandInt(0, 25);
self.applyNewWord = function(){
$("#myTarget").click(function(){
$(this).html(self.word);
});
};
}
make copy of this and don't keep document.ready inside function
I am trying working with knockout.js - mouseover and mouseout. I am bit new with Knockout. What I have done below:
<h2 id="popup" data-bind="event: { mouseover: PK.showdiv, mouseout: PK.hidediv }">
Search
</h2>
and I have my script block like below:
#section Javascript
{
<script type="text/javascript">
$(function () {
PK.showdiv = function () {
alert("Showed");
};
PK.hidedivOver = function () {
alert("Hidden");
};
})
This works fine if I use normal JavaScript call with "onmouseover" or "onmouseout". But the knockout.js call like data-bind with events is not working.
I am using MVC with Razor view.
I've created some example in jsFiddle Click here to see an example
So, in general I've created two functions on my ViewModel with names 'showdiv' and 'hidediv'
Javascript Code:
Note: we should apply bindings for our viewModel in the bottom of our js code (calling ko.applyBindings(new viewModel()); )
var viewModel = function(data) {
var self = this;
self.action = ko.observable("Hidden");
self.showdiv = function () {
//alert('Showed');
self.action("Showed");
$('#mySpan').addClass('redColor');
};
self.hidediv = function () {
//alert('Hidden');
self.action("Hidden");
$('#mySpan').removeClass('redColor');
};
};
ko.applyBindings(new viewModel());
HTML Code:
<div data-bind="event: { mouseover: showdiv, mouseout: hidediv }">Search</div>
<span id="mySpan" data-bind="text: action"></span>
CSS Code
div{
width: 100px;
height: 100px;
border: 1px solid #222;
}
span{
margin: 20px;
}
.redColor{
color: red;
}
START EDIT
Sorry, forgot to mention your mistakes:
1. You didn't initialize PK as
var PK = this;
2. In HTML code you don't need to call you functions using PK, just put the function's names:
<h2 id="popup" data-bind="event: { mouseover: showdiv, mouseout: hidediv }">
Search
</h2>
3. In javasript code you have incorrect function name like 'hidedivOver', so you should rename this function to 'hidediv' or you can rename function 'hidediv' in HTML Code to 'hidedivOver'
4. You didn't create view model and didn't apply it to knockout
END EDIT
Does it answer your question?
Thanks.
It seems to me that your didn't call applyBindings function:
ko.applyBindings(PK);
Also I don't see how you initialize PK object.
Make sure that you call applyBindings when page is ready. For this you can put it at the botton of the page or inside $(document).ready.