How to use this piece of code in a function - javascript

I have this jQuery code:
var vis = (function(){
var stateKey, eventKey, keys = {
hidden: "visibilitychange",
webkitHidden: "webkitvisibilitychange",
mozHidden: "mozvisibilitychange",
msHidden: "msvisibilitychange"
};
for (stateKey in keys) {
if (stateKey in document) {
eventKey = keys[stateKey];
break;
}
}
return function(c) {
if (c) document.addEventListener(eventKey, c);
return !document[stateKey];
}
})();
vis(function(){
document.title = vis() ? 'Visible' : 'Not visible';
});
What it does now is to change the document title of the page. If the page is not visible, it will be changed to that and vise verca.
My question is, how can I use this function like this:
if page is visible{
//do something
}
if page is not visible{
//do something else
}

Your vis() function is binding an event handler when it's passed one, otherwise returning the status. Thus:
vis(function(event) {
if ( vis() ) {
// visible
} else {
// not visible
}
});
Or more verbosely:
var handler = function(){
// calling vis() with no arguments will return a boolean
if (vis()) {
// visible
} else {
// not visible
}
}
// if a handler is passed, it gets bound to the event
// thus, runs on *any* visibility state change
vis(handler);

Related

jQuery, on input[type=radio] change verify something if false, call 2 other functions

I am trying to create an event that fires some functions depending on the id of an input[type=radio]. If the Id clicked is different to maybe_evtDiag, it should call this.applySubConditionalRequired(); and this.bindUISubActions();. Why is my code not working?
var SubFormStuff = {
init: function()
this.applySubConditionalRequired();
this.bindUISubActions();
},
bindUISubActions: function() {
// when a radio or checkbox changes value, click or otherwise
$("input[type='radio'].stepThreeDiag").change(function() {
if($(this).attr("id") == "maybe_evtDiag") {
$(this).prop('checked', false);
}else{
//this is not working //
applySubConditionalRequired(this);
displaySubFormRequired(this);
}
});
},
applySubConditionalRequired: function() {
$(".require-if-subevent-active").each(function() {
var el = $(this);
// does something
});
},
displaySubFormRequired: function() {
$(".div-subevent-class").each(function() {
var el = $(this);
// does something else
});
}
};
SubFormStuff.init();
Like you did in the init(), add a reference to the object (this) to call a sibling function (not to lose the context):
bindUISubActions: function() {
var _SubFormStuff = this;
// when a radio or checkbox changes value, click or otherwise
$("input[type='radio'].stepThreeDiag").change(function() {
if($(this).attr("id") == "maybe_evtDiag") {
$(this).prop('checked', false);
} else{
_SubFormStuff.applySubConditionalRequired();
_SubFormStuff.displaySubFormRequired();
}
});
More details on scope and context in JavaScript
You should call the methods like this:
bindUISubActions: function() {
// Store the reference to the current object
var self = this;
// when a radio or checkbox changes value, click or otherwise
$("input[type='radio'].stepThreeDiag").change(function() {
if($(this).attr("id") == "maybe_evtDiag") {
$(this).prop('checked', false);
} else{
self.applySubConditionalRequired();
self.displaySubFormRequired();
}
});
}
This way you can assing to self the current scope, and use it later on any other function call in the same execution scope.
More about javascript scope
You are trying to call applySubConditionalRequired(this) and displaySubFormRequired(this) in the wrong context you should get applySubConditionalRequired and displaySubFormRequired are not defined.
Try this:
bindUISubActions: function() {
// when a radio or checkbox changes value, click or otherwise
var that = this;
$("input[type='radio'].stepThreeDiag").change(function() {
if($(this).attr("id") == "maybe_evtDiag") {
$(this).prop('checked', false);
}else{
//it should work now //
that.applySubConditionalRequired(this);
that.displaySubFormRequired(this);
}
});
},

Remove javascript function override

I have a java script function override that occurs when certain condition is met. How can I reset these functions to its original state if I don't need it anymore.
function setProductFields() {
if (shouldShow == 'true') {
selectField = function() {
//override
}
} else {
selectField() <--- //return to its original state
}
}
Save a reference to the old selectField in a variable, prior to changing it:
var oldSelectField = selectField;
// ... other code ...
function setProductFields() {
if (shouldShow == 'true') {
selectField = function() {
//override
}
} else {
selectField = oldSelectField;
}
}

JS Event Disabler: Can't stop native eventlisteners from executing

I am implementing a JS Event-Disabler class, to disable all Native and Programmable eventlisteners of a certain dom element and all its children.
So far I've been able to disable all JQuery events and the default browser events, but not the eventlisteners set like
document.getElementById('cin').addEventListener("click", function(){
alert('I should not alert when disabled');
});
So clicking on the element ('native element') shouldn't alert, but it does.
How do I stop that from happening, within my nothing function.
If there is away to not even need to call another function but just disable all events then that would also be fine, but need to be able to re-enable all again.
Also, I can assure you that the nothing() function executes first.
var tellme = function(who) {
//console.info('Event by: '+who+' #'+Date.now());
alert('Event by: ' + who + ' #' + Date.now());
}
$(window).load(function() {
/* SOME FUNCTION TO ENSURE OUR FUNCTIONS ARE THE FIRST TO BE CALLED */
$.fn.bindFirst = function(name, fn) {
this.on(name, fn);
this.each(function() {
var handlers = $._data(this, 'events');
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
var listeners = handlers[key];
if (listeners.length > 1) {
var lastEvent = listeners.pop();
listeners.splice(0, 0, lastEvent);
if (listeners[1].handler.name === lastEvent.handler.name)
listeners.splice(1, 1);
}
}
}
});
};
function shouldbenothing() {
tellme('native catcher');
nothing();
}
/* THE DO NOTHING FUNCTION, NEEDS SOMETHING MORE, DOESN'T CANCEL ALL*/
function nothing() {
event.cancel = true;
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
//Needed for Jquery
throw new Error("NOT AN ERROR: Just forcefully stopping further events #" /*+Date.now()*/ ); //Add the Date.now to see that this code does run before the native function.
return false;
}
/* THIS WILL ONLY RETURN NON-NATIVE EVENTS, ONLY PROGRAMMED EVENTS*/
function getAllActiveEvents(element) {
var result = [];
var handlers = $._data(element, 'events');
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
result.push(key);
}
}
return result.join(' ');
}
function getAllEvents(element) {
var result = [];
for (var key in element) {
if (key.indexOf('on') === 0) {
result.push(key.slice(2));
}
}
return result.join(' ');
}
/*SOME PROGRAMMED EVENTS, BESIDES THE NATIVE ONES*/
$('input').on('keyup', function() {
$('#text').html(this.value);
});
$('p').on('click', function() {
$('#text').html(this.innerHTML);
tellme('jquery');
});
document.getElementById('jsE').addEventListener("click", function() {
tellme('p:js');
});
document.getElementById('cin').addEventListener("click", function() {
tellme('input:js');
});
/* THE ACTUAL DISABLER CODE */
/*TOGGLE TO ACTIVE OR DISABLE EVENTS FROM TAKING PLACE NATIVE AND EXTRA*/
var isOn = false;
$('button').on('click', function() {
if (isOn)
$("#obj *").each(function() {
$(this).off(getAllEvents($(this)[0]), "", nothing);
$("#obj").css('pointerEvents','');
});
else {
$("#obj *").each(function() {
var elem = $(this)[0];
var events1 = getAllActiveEvents(elem); //Only programmed listeners
var events2 = getAllEvents(elem); //Native + other listeners
$(this).bindFirst(events2, nothing);
});
$("#obj").css('pointerEvents','none');
}
isOn = !isOn;
this.innerHTML = isOn;
});
});
p {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<style>p {pointer:hand;}</style>
<div id="obj">
<p>jquery event</p>
<p id="jsE">js event</p>
<p onclick="tellme('native');">native event</p>
<input id='cin' type="text" />
<p id="text">3</p>
</div>
<p>not catched</p>
<input type="text">
<button>toggle</button>
There might be a very simple, non-js, pure css-solution ... like this:
.whatever {
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
pointer-events:none;
}
... just add the whatever-class to any elements you want to disable completely from user-interaction.
So I found a solution shortly after.
By playing with the css code, I could disable all the relevant mouse events. This however doesn't stop the native events, say if you were to trigger the event via JS, but at least it stops it from user's point.
I actually also like the css method better, as it does allow me to still interact and trigger events, for instance when I want to show the user something without having the user interfere.
The css code:
//To Disable
$("#obj").css('pointerEvents','none');
//To Enable
$("#obj").css('pointerEvents','');
For anyone looking for the full Working Code: Here it is.
Make sure you add the css.
/* Event Disabler, disables all events */
/* How to use:
* Toggle Events: toggleEvents(selector);
* Disable all Events: toggleEvents('body',true);
* Enable all Events: toggleEvents('body',false);
*/
var toggleEvents = null;
$(window).load(function(){
/* SOME FUNCTION TO ENSURE OUR FUNCTIONS ARE THE FIRST TO BE CALLED */
$.fn.bindFirst = function(name, fn) {
this.on(name, fn);
this.each(function() {
var handlers = $._data(this, 'events');
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
var listners = handlers[key];
if (listners.length > 1) {
var lastEvent = listners.pop();
listners.splice(0, 0, lastEvent);
//Removes duplicate eventListners
if (listners[1].handler.name === lastEvent.handler.name)
listners.splice(1, 1);
}
}
}
});
};
/* THE DO NOTHING FUNTION CANCELS ALL EVENTS, EVEN BY TRIGGERED*/
function nothing() {
event.cancel = true;
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
event.bubbles = false;
if(window.event){
window.event.cancelBubble=true;
}
//throw new Error("NOT AN ERROR: Forcefully stopping further events");
return false;
}
function getAllActiveEvents(element) {
var result = [];
var handlers = $._data(element, 'events');
for (var key in handlers) {
if (handlers.hasOwnProperty(key)) {
result.push(key);
}
}
return result.join(' ');
}
function getAllEvents(element) {
var result = [];
for (var key in element) {
if (key.indexOf('on') === 0) {
result.push(key.slice(2));
}
}
return result.join(' ');
}
var enabled = false;
toggleEvents = function(selector,flag) {
enabled = flag === undefined ? !enabled : flag;
if (enabled) {
$(selector+" *").each(function(){
//Only programmed and attached listners
var events1 = getAllActiveEvents($(this)[0]);
//All Native events attached or not
var events2 = getAllEvents($(this)[0]);
$(this).bindFirst(events2, nothing );
});
//Disabled most user pointer events
$(selector).addClass('eventsDisabled');
} else {
$(selector+" *").each(function() {
$(this).off(getAllEvents($(this)[0]), "", nothing );
});
$(selector).removeClass('eventsDisabled');
}
};
});
.eventsDisabled {
-webkit-user-select:none !important;
-moz-user-select:none !important;
-ms-user-select:none !important;
user-select:none !important;
pointer-events:none !important;
}

Define a javascript variable under conditions with jquery

Like the title says, I would like to fill a variable up under some conditions
I thought I could do like that but no :
var content = $(function() {
if ($('#content').length) {
return $('#content');
}
if ($('#content_no_decoration').length) {
return $('#contenu_no_decoration');
}
if ($('#full_content').length) {
return $('#full_content');
}
if ($('#full_content_no_decoration').length) {
return $('#full_content_no_decoration');
}
});
So I thought that the javascript variable 'content' would be one of the jquery object representing an element in the dom. But it seems that 'content' is the function.
I guess you imagine what i want to do.. What is the syntax with JQuery ?
Thank you
$(function() { }) is short-code for the DOMReady event. You need to explicitly define a function, and then assign the return value to your variable.
For example:
function getObj()
{
if($('#content').length)
{
return $('#content');
}
if($('#content_no_decoration').length)
{
return $('#contenu_no_decoration');
}
if($('#full_content').length)
{
return $('#full_content');
}
if($('#full_content_no_decoration').length)
{
return $('#full_content_no_decoration');
}
}
You can then assign the value as :
var content = getObj();
You will need to call the assignment when the DOM is ready though, otherwise the selectors will not trigger as expected. For example:
$(function() {
var content = getObj();
});
You are only declaring the function, so content contains a pointer to the function.
Execute it and you are fine:
var content = function() {
if ($('#content').length) {
return $('#content');
}
if ($('#content_no_decoration').length) {
return $('#contenu_no_decoration');
}
if ($('#full_content').length) {
return $('#full_content');
}
if ($('#full_content_no_decoration').length) {
return $('#full_content_no_decoration');
}
}();
But you don't really need a function here. If the script tag is at the bottom of the page (right before the closing </body>-tag), or the assignment is within a load handler you could use:
var content = $('#content').length
? $('#content')
: $('#content_no_decoration').length
? $('#content_no_decoration')
: $('#full_content').length
? $('#full_content')
: $('#full_content_no_decoration').length
? $('#full_content_no_decoration')
: undefined;
Or use jQuery to your advantage and keep things really short:
var content =
$('#content,#content_no_decoration,#full_content,#full_content_no_decoration')
.get(0);
// if none of the elements exist, content will be undefined, otherwise
// it will contain [a JQuery Object of] the first existing element
why you don't do like that ?
function thatsAGoodName() {
if ($('#content').length) {
return $('#content');
}
if ($('#content_no_decoration').length) {
return $('#contenu_no_decoration');
}
if ($('#full_content').length) {
return $('#full_content');
}
if ($('#full_content_no_decoration').length) {
return $('#full_content_no_decoration');
}
}
var content = thatsAGoodName();
The function
$(function() {
// DOM safe to use do stuff
})
Is shorthand for the document ready event. This tells you the coder that the dom is safe to use.
You would not really return anything from this event.
content is an object because you're setting it to a object here:
var content = $(function() {
What you probably intended was:
var content;
if ($('#content').length) {
content = $('#content');
}
if ($('#content_no_decoration').length) {
content = $('#contenu_no_decoration'); // Is #contenu a typo???
}
if ($('#full_content').length) {
content = $('#full_content');
}
if ($('#full_content_no_decoration').length) {
content = $('#full_content_no_decoration');
}
Note, that this will have a reference to an element now. If you want the actual content you'll need to pull it out with something like html() or val().
You are using the shorthand for the jQuery ready event ($(function() {. What I believe you want is a self invoking function:
// remove the call to jQuery
var content = (function() {
if ($('#content').length) {
return $('#content');
}
// ... more
})(); // invoke the function, which should return a jQuery object
You may need to wrap this in a document.ready, depending on where your script is executed.
Rearrange it a little bit and it should work:
$(function () {
var content = (function() {
var regularContent = $('#content');
if (regularContent.length !== 0) {
return regularContent;
}
var contentNoDecoration = $('#content_no_decoration');
if (contentNoDecoration.length !== 0) {
return contentNoDecoration;
}
var fullContent = $('#full_content');
if (fullContent.length !== 0) {
return fullContent;
}
var fullContentNoDecoration = $('#full_content_no_decoration');
if (fullContentNoDecoration.length !== 0) {
return fullContentNoDecoration;
}
}());
});
This code is basically saying once the DOM is ready (the $(function () { ... }); part), run this anonymous function (the (function () { ... }()); part) and assign its return value to content.
Edit: Also, you're losing efficiency by running each of your selectors twice instead of just once.
It's true that content is the function, but you can use that function. Like:
var result = content();
Edit:
Remove the $() around var content = $({/* code */}) and it works.

How do I add a function to an element via jQuery?

I want to do something like this:
$('.dynamicHtmlForm').validate = function() {
return true;
}
$('.dynamicHtmlForm .saveButton').click(function() {
if (!$(this).closest('.dynamicHtmlForm').validate()) {
return false;
}
return true;
});
And then when I have a form of class dynamicHtmlForm, I want to be able to provide a custom validate() function:
$('#myDynamicHtmlForm').validate = function() {
// do some validation
if (there are errors) {
return false;
}
return true;
}
But I get this when I do this:
$(this).closest(".dynamicHtmlForm").validate is not a function
Is what I've described even possible? If so, what am I doing wrong?
Yes, it is technically possible. You will need to reference the element itself, however, and not the jQuery collection. This should work:
$('.dynamicHtmlForm').each(function (ix,o) {
o.validate = function() {
return true;
}
});
$('.dynamicHtmlForm .saveButton').click(function() {
if ($(this).closest('.dynamicHtmlForm')[0].validate()) {
return false;
}
return true;
}
jQuery.fn.validate = function(options) {
var defaults = {
validateOPtions1 : '',
validateOPtions2 : ''
};
var settings = $.extend({}, defaults, options);
return this.each(function() {
// you validation code goes here
});
};
$(document).ready(function() {
$('selector').click(function() {
$('some selector').validate();
// or if you used any options in your code that you
// want the user to enter. then you go :
$('some selector').validate({
validateOPtions1: 'value1',
validateOPtions2: 'value2'
});
});
});
You're not adding the function to the element, you're adding it to the jQuery wrapper around the element. Every time you pass a selector to jQuery, it will create a new wrapper for the found elements:
$('#myEl'); // gives a jQuery wrapper object
$('#myEl'); // creates another jQuery wrapper object
If you save the wrapped element to a variable and use that later, it would be a different story because you're accessing the saved jQuery wrapper object.
var dynamicHtmlForm = $('.dynamicHtmlForm');
dynamicHtmlForm.validate = function() {
return true;
}
$('.dynamicHtmlForm .saveButton').click(function() {
if (dynamicHtmlForm.validate()) {
return false;
}
return true;
}
You could also add the function directly to the element using
$('.dynamicHtmlForm')[0].validate = function () { return true; }
// and later...
if (!$(this).closest('.dynamicHtmlForm')[0].validate())
Or you could look at extending jQuery properly by writing a plugin.

Categories

Resources