I'm using jQuery autoResize plugin based on James Padolsey.
In that plugin i'm trying to bind events and when i do
$(this).trigger('keydown.dynSiz',doResize); within hideXDiv() function
doResize doesn't get called... but $(this).trigger('keydown.dynSiz',doResize); in showXDiv() gets called.
Below is the code
textarea
.unbind('.dynSiz')
.bind('keyup.dynSiz', doResize)
.bind('keydown.dynSiz', doResize)
.bind('focus',showXDiv)
.bind('focusout',hideXDiv)
.bind('change.dynSiz', doResize);
});
doResize = function() {
alert("...");
}
showXDiv = function()
{
if(id != null)
{
$(this).trigger('keydown.dynSiz',doResize); //get called!
$($(this).attr('mydiv')).show();
}
}
hideXDiv = function()
{
if(id != null)
{
$(this).trigger('keydown.dynSiz',doResize); //this trigger doesn't happen....
$($(this).attr('mydiv')).slideUp();
}
}
Related
Working on a Drupal 9 site and trying to add some custom JS code to a page.
Drupal.behaviors.syfyGlobalHideMenu = {
attach: function (context, settings) {
$('.nav-flyout', context).once('remove-modals', function () {
$(document).keyup(function (e) {
if (e.keyCode == 27) {
$('.nav-flyout', context).removeClass('js-flyout-active');
}
});
});
}
};
Wondering if there's a vanilla JS equivalent to the jQuery .once functionality above?
Currently Drupal attaches the event listener multiple times and I am trying to avoid that as I only want to attach the event listener once but have it remain attached and run every time the event is invoked.
let intervalID = null;
const search = document.querySelector(".call-us-table input#edit-search");
search.addEventListener("keydown", event => {
form.setAttribute("onsubmit", "return false");
clearInterval(intervalID);
});
search.addEventListener("keyup", event => {
intervalID = setInterval(submitForm, 2000);
});
Jquery once adds an html attribute to check if is the first time to run.
function vanillaOnce() {
if (!document.body.getAttribute('data-once')) {
document.body.setAttribute('data-once', 'true');
return true;
} else {
return false;
}
}
if (vanillaOnce) {
console.log('runs only once');
}
I'm trying to capture if the enter key has been pressed and execute a search. This is the viewmodel for the search page.
(function ()
{
a.viewModels.userSearch = function (view, params) {
$view = $(view);
var self = a.viewModel({
users: a.collection({
url: '/admin/Account/SearchUsers',
query: {
SearchText: null
}
}).fetch(),
setPageIndex: setPageIndex,
search: search
});
$view.keypress(function (e) {
if (e.keyCode == 13) {
self.search(e);
}
});
function search(e) {
self.users.query.rowCount = 0;
self.users.query.pageIndex = 1;
self.users.fetch();
}
function setPageIndex(e) {
e.preventDefault();
self.users.query.set('pageIndex', $(e.currentTarget).data('page-index'));
self.users.fetch();
}
return self;
}
Now, this works. The problem is that it works only after pressing the 'Enter' key 2 times. Seems like I'm missing something related to the scope but js ain't my cup of tea.
If it is of any help, here goes my view model function:
function viewModel(viewModelConfig) {
var self = kendo.observable($.extend({
busy: 0,
resultMessage: null,
clearResultMessage: clearResultMessage
}, viewModelConfig));
self.bind('change', onChange);
function onChange(change) {
var errorProp, errorMsg, infoProp, infoMsg;
if (change.field.endsWith('.busy')) {
if (self.get(change.field))
self.set('busy', self.busy + 1);
else if (self.busy > 0)
self.set('busy', self.busy - 1);
}
else if (change.field.endsWith('.resultMessage')) {
var data = self.get(change.field);
self.set('resultMessage', data);
}
}
function clearResultMessage(e)
{
if (e) e.preventDefault();
self.set('resultMessage', null);
return false;
}
return self;
}
I have a similar setup on my site, and using MVVM, just add the custom enter binding within the data-bind attribute of the element to link to the function within the view-model you wish to execute.
The code to add the custom binder is as such:
kendo.data.binders.widget.enter = kendo.data.Binder.extend({
init: function(element, bindings, options) {
kendo.data.Binder.fn.init.call(this, element, bindings, options);
var binding = this.bindings.enter;
$(element.element).keyup(function(e) {
if( e.which === 13 )
bindings.get();
});
},
refresh: $.noop
});
is there any way, how can I globally (in service) disable and enable all ng-click and ng-submit events?
For example when user is offline I want to disable all actions till he gets connection back..
I tried to bind all elements with an onClick event which will call stopImmediatePropagation but it didn't work..
$('*[ng-click]').click(function( event ) {
event.stopImmediatePropagation();
});
Also this question is a little bit different from this one:
Disable ng-click on certain conditions of application for all types of element
I'd like to disable/enable all events in APP globally from service, I'm not able to modify all ng-* calls on all elements in the APP..
Try including a return false too:
$('*[ng-click]').click(function( event ) {
event.stopImmediatePropagation();
return false;
});
Snippet
The below snippet demonstrates that multiple event handlers attached to a single <a> works too.
$(function () {
$("a").click(function () {
alert("Hello!");
return false;
});
$("a").click(function () {
alert("Bye!");
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Click Me
So finally I end up with temporarily disabling all events on the page using jquery..
I got inspired from this plugin http://ignitersworld.com/lab/eventPause.html which for some reason did not work (without any error)
So I took main parts and put it to this class which is working now using jquery v2.1.1:
var EventManager = function() {
var self = this;
var nullFun=function(){};
var getIndex = function(array,value){
for(var i=0; i< array.length; i++){
if(array[i]==value){
return i;
}
}
return -1;
};
this.pauseEvent = function(elm,eventAry){
var events = $._data(elm, "events");
if (events) {
$.each(events, function(type, definition) {
if((getIndex(eventAry,type)!=-1)||(eventAry=='')){
$.each(definition, function(index, event) {
if (event.handler.toString() != nullFun.toString()){
if(!$._iwEventPause) $._iwEventPause = {};
$._iwEventPause["iw-event" + event.guid] = event.handler;
event.handler = nullFun;
}
})
}
})
}
};
this.activeEvent = function(elm,eventAry){
var events = $._data(elm, "events");
if (events) {
$.each(events, function(type, definition) {
if((getIndex(eventAry,type)!=-1)||(eventAry=='')){
$.each(definition, function(index, event) {
if (event.handler.toString() == nullFun.toString()){
event.handler = $._iwEventPause["iw-event" + event.guid];
}
})
}
})
}
};
this.disableAll = function(el) {
el = el || $('*');
el.each(function() {
self.pauseEvent($(this)[0], '');
});
self.pauseEvent($(window)[0], '');
};
this.enableAll = function(el) {
el = el || $('*');
el.each(function() {
self.activeEvent($(this)[0], '');
});
self.activeEvent($(window)[0], '');
};
return this;
};
var eManager = new EventManager();
eManager.disableAll();
eManager.enableAll();
This will go through window object and all elements on the page, move their event handlers away to _iwEventPause object and replace handlers with dummy function.. When enabling, it will move handlers back so they get normally called..
This solution does not handle event handlers added after disabling..
Given the jQuery dropdown plugin below. Is there a way to add a method that would allow for a separate function outside of the dropdown to 'hideMenu'? Thanks
For example, if I applied the plugin to a div with an ID like so:
$('#settings.dropdown').dropDownMenu();
How could I then call to close the dropDownMenu w hideMenu from outside of the plugin? Thanks
jQuery.fn.dropDownMenu = function() {
// Apply the Dropdown
return this.each(function() {
var dropdown = $(this),
menu = dropdown.next('div.dropdown-menu'),
parent = dropdown.parent();
// For keeping track of what's "open"
var activeClass = 'dropdown-active',
showingDropdown = false,
showingMenu,
showingParent,
opening;
// Dropdown Click to Open
dropdown.click(function(e) {
opening = true; // Track opening so that the body click doesn't close. This allows other js views to bind to the click
e.preventDefault();
if (showingDropdown) {
dropdown.removeClass(activeClass);
parent.removeClass(activeClass);
showingMenu.hide();
showingDropdown = false;
} else {
showingDropdown = true;
showingMenu = menu;
showingParent = parent;
menu.show();
dropdown.addClass(activeClass);
parent.addClass(activeClass);
}
});
// When you click anywhere on the page, we detect if we need to blur the Dropdown Menu
$('body').click(function(e) {
if (!opening && showingParent) {
var parentElement = showingParent[0];
if (!$.contains(parentElement, e.target) || !parentElement == e.target) {
hideMenu();
}
}
opening = false;
});
// hides the current menu
var hideMenu = function() {
if(showingDropdown) {
showingDropdown = false;
dropdown.removeClass(activeClass);
parent.removeClass(activeClass);
showingMenu.hide();
}
};
});
};
jQuery advises making multiple methods available through the plugin itself:
jQuery.fn.dropDownMenu = function(method) {
var methods = {
init: function() {
// Put all your init code here
},
hide: function() {
hideMenu();
}
};
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
function hideMenu() {
// ...
}
};
See http://docs.jquery.com/Plugins/Authoring#Plugin_Methods
Update: Use like this:
// Use the plugin normally to run the init method
$('#settings.dropdown').dropDownMenu();
// Call the hide method
$('#settings.dropdown').dropDownMenu('hide');
Sure. Give hideMenu to the global window object, like this:
window["hideMenu"] = function() {
if(showingDropdown) {
showingDropdown = false;
dropdown.removeClass(activeClass);
parent.removeClass(activeClass);
showingMenu.hide();
}
};
You can then call it as usual anywhere you need to.
HTML part:
foo
JS part:
function callme() {
var me = ?; //someway to get the dom element of the a-tag
$(me).toggle();
}
in the JS part can i somehow get the a-tag that this function was called from?
i know i could just pass it as a parameter, but this function is used many many times on a page and i want to avoid putting the parameter everywhere.
thanks!
Since you are using an onclick attribute (BAD!) you have to pass that into the function.
onclick="callme(this); return false;"
and the js:
function callme(el) {
var $me = $(el);
$me.doSomething();
}
Another option is to set the context of the function using .call().
onclick="callme.call(this,event)"
and the js
function callme(event) {
event.preventDefault();
$(this).doSomething();
}
I have a simple JS function for that
function getEventTarget(event) {
var targetElement = null;
try {
if (typeof event.target != "undefined") {
targetElement = event.target;
}
else {
targetElement = event.srcElement;
}
// just make sure this works as inteneded
if (targetElement != null && targetElement.nodeType && targetElement.parentNode) {
while (targetElement.nodeType == 3 && targetElement.parentNode != null) {
targetElement = targetElement.parentNode;
}
}
} catch (ex) { alert("getEventTarget failed: " + ex); }
return targetElement;
};
in your html
foo
in your function
function callme(event) {
var me = getEventTarget(event); //someway to get the dom element of the a-tag
$('#'+ me.id).toggle();
}
getEventTarget() will bring back the whole dom object which you can manipulate as you please, or has been said already by other users you can just use
function callme(event) {
$(this).toggle();
}
send this parameter to your function.
foo
function callme(me) {
$(me).toggle();
}
better dont use onlcick in html markup
$(document).ready(function() {
$("a").click(callme);
})
function callme() {
var me = this;
$(me).toggle();
}