"Hiding" javascript events in DOM - javascript

I'm developing a custom ordering process and I'm using AJAX requests and dynamic forms a lot to complete parts of the ordering process, but I'd like to cleanup the way I'm doing it into terms of the HTML. I'm using jQuery too.
In looking at applications like Google's word processor, I can see that both the DOM and source exhibit no javascript event attributes. For example:
<div id="docs-file-menu" role="menuitem" class="menu-button goog-control goog-inline-block" aria-disabled="false" aria-expanded="false" aria-haspopup="true" style="-webkit-user-select: none;">File</div>
My guess is that a script is registering Javascript events after the fact based on the HTML attributes.
My website is much less complex, but I was wondering how to approach this as I currently have button styled <a><img></a> tags (or similar) that call Javascript functions, which works fine, but seems like the lesser (and old school) approach. For example:
<a href="javascript:Customisation.beginNewPair()">
<img src="images/begin-new.gif" />
</a>

Here is a simple example on how to use data attributes and an eventListener on click:
var a = document.getElementById('docs-file-menu');
a.addEventListener('click', test);
function test () {
var dis = a.getAttribute('aria-disabled');
var exp = a.getAttribute('aria-expanded');
var has = a.getAttribute('aria-haspopup');
if (dis == 'true') {
alert('disabled = true');
}
if (exp == 'true') {
alert('expanded = true');
}
if (has == 'true') {
alert('haspopup = true');
}
}
You also could access the different data attributes on page load and, according to them, you could be running different functions.
Here's a simple DEMO with onclick event, simply click on File

What you want is addEventListener.
How you access the elements is another question, but say you want an alert every time somebody clicks on a box.
var box = document.getElementById('box');
box.addEventListener('click', function(){ alert(); });
<div id="box" style="width:150px;height:150px;background:blue;"></div>
You can also put what happens in a real function:
function doSomething(){
alert();
}
var box = document.getElementById('box');
box.addEventListener('click', doSomething);
<div id="box" style="width:150px;height:150px;background:blue;"></div>

Related

Is there a better way to include jquery event handlers with xmlhttprequest()

I've written the real-time form validation necessary for my Site. It's included in my javascript/jquery.js file and does things like:
//Let user know if they've left an invalid email in the field
$signupEmail.on("blur", function() {
var form = new SignupForm($signupEmail.val());
if ( !form.isEmailEmpty() && !form.isEmailValid() ) {
form.showEmailError("Invalid email");
} else {
form.isEmailRegistered();
if (!form.emailError && form.isEmailValid()) {
form.hideEmailError();
form.showValidEmail();
}
}
});
and:
//Let user know when they've entered a valid email
$signupEmail.on("keyup", function() {
var form = new SignupForm($signupEmail.val());
var userEmail = form.userEmail();
$.post("/sitename/scripts/checkEmailAvailability.php", {"userEmail": userEmail}, function (data) {
if (form.isEmailValid() && !data) {
form.showValidEmail();
} else {
form.hideEmailError();
}
});
});
This and the rest of the code works flawlessly with my signup and contact forms.
I also have a directory called users/ with a sub-directory called account-settings/. Each page in the sub-directory contains a different form users can submit to update their account. For instance, there is an update-email.php, update-password.php, etc. These pages are loaded onto an account-settings.php page through an xmlhttprequest(). The problem I'm having is figuring out an efficient way of including the jquery real-time validation, which doesn't seem to work unless included in the xmlhttp.onreadystatechange function. As it is now, I have to include the jquery validation twice; One for the signup/contact forms and another for the account-settings forms. Please review the following code:
Site/users/account-settings/account-settings.php
//php includes
//session configurations
<div id="user-settings">
<ul>
<li>Update Email</li>
<li>Update Password</li>
<li>Update Photo</li>
<li>Manage Friends</li>
</ul>
</div>
<div id="user-settings-forms">
</div>
//php include footer
Site/javascript/jquery.js
//Show User Profile's Settings Forms
$("#user-settings li").on('click', function() {
var data = $(this).find('a').attr('href');
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
document.getElementById("user-settings-forms").innerHTML = xmlhttp.responseText;
// I'm currently duplicating all of the real-time validation here
// If I move the code anywhere else, it doesn't work
// This makes for a lot of redundancy
// I also don't know how this affects the xmlhttprequest
}
}
if (data === '#update-email') {
xmlhttp.open('POST', 'update-email.php');
} else if (data === '#update-password') {
xmlhttp.open('POST', 'update-password.php');
} else if (data === '#update-photo') {
xmlhttp.open('POST', 'update-photo.php');
} else if (data === '#manage-friends') {
xmlhttp.open('POST', 'manage-friends.php');
}
xmlhttp.send();
});
Things I've tried so far:
1. Including the necessary jquery code on the update-email.php, update-password.php pages. I thought: well, if I include the code directly on the page that would be using it, it should always work regardless of whether the page is passed through an xmlhttprequest or not. But, I was wrong. It doesn't work.
2. Remove require("templates/header") from the update-email.php, update-password.php pages. This template includes, among other things, all the links to my css and js files. I thought: maybe there is a collision of the templates happening when the page is sent through the xmlhttprequest function. It only seemed half logical since the css was still rendering without a problem but, it was worth a shot.
3. Including the javascript file asynchronously, the same way I would a Google map. I thought: since the xmlhttprequest happens asynchronously, adding the script asynchronously may be necessary. But, that didn't work either.
So, is there a more efficient way of including the jquery events handlers that belong with the page passed through an xmlhttprequest object? If this is the only way, how does it affect the xmlhttprequest? Slow it down? No change at all? Will adding too much code cause a problem with the script in any way? Thank you. I really appreciate any help you can give.
The issue is that by assigning to innerHTML on the form, you're destroying the elements you have the handlers attached to, and replacing them with new elements you don't have handlers attached to.
This is a good use case for event delegation: You hook the event on the form, not the element, but tell jQuery to only notify you of the event when it passes through a given element during the bubbling phase. So suppose your $signupEmail field has name="user-email" or some such (you haven't shown it, so I'm just picking something as an example). To handle blur on it:
$("#user-settings-forms").on("blur", "input[name=user-email]", function() {
/// Your validation logic here, this will refer to the user-email field
});
jQuery makes events like blur and focus bubble even on browsers where they don't natively.
More about event delegation in the .on documentation.
The above hooks up specifically the user-settings-forms element, but you could use a common class on both forms to avoid making it specific like that, so you can include your validation script on both pages without modification.
Here's an example using a .user-form-validate class:
$(".user-form-validate").on("blur keyup", "input[name=user-email]", function(e) {
var $this = $(this),
$validation = $this.closest("label").next(".validation-error");
if (!$.trim($this.val())) {
if (e.type === "blur" || e.type === "focusout") {
$validation.text("Please fill in an email address").fadeIn();
}
} else {
$validation.fadeOut();
}
});
.validation-error {
color: #a00;
}
<form class="user-form-validate">
<label>Email address:
<input type="text" name="user-email">
</label>
<p class="validation-error" style="display: none"></p>
<div>
<input type="button" value="Fake Send Button">
</div>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Javascript/Jquery Boolean help: Hiding/Showing Divs

Can someone explain to me what i am doing wrong in this code?
http://jsfiddle.net/14njfqef/
var isLoggedIn = function(state){
if(state == true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else(state == false){
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
}
onload=function() {
isLoggedIn(false);
}
On load i want the divs to hide but then when i click the button i want the divs to show?
Is the boolean function set out in the correct way?
Piece below tries to re-arrange piece at OP. onload not appear clearly defined , not addressed , though could be attached to an event , i.e.g., window.onload = onload . Wrapped blocks in jquery .ready() event . Removed js onclick markup from html , included at script element , or loaded from file at jquery .on("click") event . Added strict comparison operator === (an added =) to if / else if statements. Changed input type to button. Added if to else portion of composition (see link posted at comments by Felix Kling).
Try
$(function() {
var isLoggedIn = function(state){
if(state === true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else if(state === false){
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
};
isLoggedIn(false);
$("input[type=button]").click(function() {
isLoggedIn(true)
})
});
jsfiddle http://jsfiddle.net/guest271314/14njfqef/3/
changed your html to
<input type="submit" value="Boolean" id="toggle"/>
rewrote your js as
// JQuery run at start effectivly
$(document).ready(function() {
function isLoggedIn(state) {
if(state == true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else {
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
}
// JQuery attaching a click event using an anonymous function
// and hard coding your isLoggedIn to true, passing variables is a bit more complicated.
$('#toggle').click(function() {isLoggedIn(true)});
isLoggedIn(false);
})
Well there's a few things I am not sure if you are aware of so I feel there's some responsibility on my end to make sure they are mentioned. They are a number of syntactical errors in your post that are stopping this from working so instead of addressing them I feel its necessary to update your view on what JQuery you are using as well as your selector choice.
First I would add a class structure to all of the div's to target them all at once so you can save on some lines of code. In production it's always better to have less code for all of your visitors to download because even a little bit of code can get out of control after enough hits on a webpage. Having to serve it kills speed and so does having to process three separate jquery selections as opposed to one.
I would change the HTML to...
<body>
<div id='content-container' class='boxes'>
Content Container
</div>
<div id='account' class='boxes'>
account
</div>
<div id='account2' class='boxes'>
account2
</div>
<input id="validateButton" type="submit" value="Boolean">
</body>
This way you can simply target all divs with $(".boxes"); ... I wouldn't recommend getting into the habbit of using $("div");
Next I would change the JQuery to being more JQuery friendly code. Its not always useful to use an onload event from pure Javascript to handle JQuery driven functions in correct time to the loading of DOM objects. Therefore you should use $( document ).ready( handler ) to handle this load event properly just in case it causes you problems down the road. The more common shorthand of this ready event is a simple $(function() { }); wrapper.
The rest of the code can be re-arranged to this....
var isLoggedIn = false; //<--Instantiate to false, make global to window level scope
//Load event Corrected For JQuery
$(function() {
$(".boxes").hide(); //<--Hide on load
//Add A Proper Updated Click Event To Button
$("#validateButton").click(function() {
isLoggedIn = true; //<--Should include real functionality not hand coded to true
checkLoginAndRespond(); //<--Validate Login Status
});
});
function checkLoginAndRespond() {
//If Logged, Show
if(isLoggedIn) {
$(".boxes").show();
//Else Don't
} else { $(".boxes").hide(); }
} //end function
Lastly, the version. New versions of JQuery have not been released for some time and seem to not be in the making so its a safe bet to use their most recent versions as it has thousands of pages of help for its syntax and it's very stable. I would recommend anything in the 2.0 or higher series JQuery.
I am assuming you have JQuery library loaded. Try
if (state) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else{
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
to solve your problem.

How can I get this Javascript to work with multiple links on the same page?

As of right now, I am able to get this javascript function to work with one link.
However, I would like to use the function with multiple links. I have changed obj to different values and have also tried using more than one function specified with different values for each to get a working prototype, but nothing seems to work. Below is the javascript function from scratch, no changes.
<script type="text/javascript">
function gObj(obj) {
var theObj;
if(document.all){
if(typeof obj=="string") {
return document.all(obj);
}
else {
return obj.style;
}
}
if(document.getElementById) {
if(typeof obj=="string") {
return document.getElementById(obj);
}
else {
return obj.style;
}
}
return null;
}
</script>
And the link code:
<div id="axphsh">
<b>Phone:</b><a href="#" onClick="
gObj('axphsh').style.display='none';
gObj('axphhd').style.display='block';
return false;">Click for Phone Number</a></div>
<div id="axphhd" style="display:none">
<b>Phone:</b> 555-555-5555</div>
Ultimately what I want is to use the link code for multiple numbers on the same page, all hidden by default, then unhidden onClick. But like I said, this only works for one phone number link, then if there are more specified on the same page, the onClick event doesn't work at all. I am thinking it has to do with getElementById since div ids for links can be specified in that manner, but I am not completely sure.
You should learn some basic JS DOM manipulation.
Why do you even use document.all which is not a part of the standard? Use document.getElementyById or document.querySelector.
If all of your boxes with phone numbers were similar you could go with a more general function:
HTML:
<div class="phone-link-container">
Click for phone number
</div>
<div class="phone-number-container">555-555-555</div>
JS:
function showNumber (e) {
var link = e.target,
link_container = e.target.parentNode,
phone_number = link_container.nextElementSibling;
link_container.style.display = 'none';
phone_number.style.display = 'block';
}
var numbers = document.querySelectorAll('.show-phone-number');
Array.prototype.forEach.call(numbers, function (el, i) {
el.addEventListener('click', showNumber);
});
It selects all elements with a class show-phone-number and binds a function showNumber to the click event for each of them. This function hides parent of the link (which would be phone-link-container in my example) and shows next sibling of the parent (which is phone-link-container).
http://jsfiddle.net/9ZF9q/2/
In case your JavaScript code is in head you need to wrap all DOM manipulations inside window load callback:
window.addEventListener("load", function () {
var numbers = document.querySelectorAll('.show-phone-number')
Array.prototype.forEach.call(numbers, function (el, i) {
el.addEventListener('click', showNumber);
});
});
You can read more on functions used there on https://developer.mozilla.org/en-US/docs/DOM/Element.nextElementSibling
When it comes to DOM manipulation if you want to keep the compatibility with all older browsers it's easier to use jQuery library - especially if you're a beginner.

how to alert user when there are changes inside an object field

how can i alert the user if there are any changes inside the object field
i''m trying to detect the changes on this div inside the object
if it's normal the code would be this:
<div id="HeaderNewMessageIcon" class="BrosixContactNewMessage" style="display:none;">
</div>
but if there are changes it will look like this:
<div id="HeaderNewMessageIcon" class="BrosixContactNewMessage" style="display: block; ">
</div>
i want to alert the user if there are changes inside the object, either via alert or using an image.
is there any way for me to achieve this?
and another thing, i have no access to the code inside the object, i can only view it but not edit it.
I believe there must be some JavaScript code which changing your html you can call your method from there. Other way you can use setInterval.
You can use jQuery plugin Mutation Events plugin for jQuery . see thread
var a = document.getElementsByClassName('HeaderNewMessageIcon')[0];
var oldTitle = a.title;
setInterval(function(){
if(a.title !== oldTitle){
alert("Title change");
oldTitle = a.title;
}
},100);
jsfiddle
You have to detect the changes when throught user interaction such as click, mouseover, mousedown, etc... then you can attach a function to see if its attributes or anything inside it changes.
//detect inputs change
$('#HeaderNewMessageIcon').find(':input').change(function(){ alert(...)});
//detect attributes change
$('#HeaderNewMessageIcon').click(function(){
detectChange(this);
});
As for detectChange to work, you must save the attributes when page just loaded
var attrs = $('#HeaderNewMessageIcon').get(0).attributes;
function detectChange(obj){
//pseudo-code, you need to find a function on the web to commpare 2 objetcs
if (obj.attributes === attrs){
alert(...);
}
//the same comparison for the children elements $(obj).children()
}

Return value from custom alert [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to create TRULY modal alerts/confirms in Javascript?
TL;DR: I've overridden the default alert() function with a custom HTML based one. I want the new dialogue to still block execution, and get the buttons within my dialogue to return true or false from the call to alert() to use in logic (and continue execution).
I'm trying to implement a custom alert box, which replaces the default browser alert with a nicely themed box with the same (or similar) functionality.
I've read this question, and I'm using the solution given in this answer (to the same question). What I want to do now is get my overridden alert to return a true or false value for use in if() statements, depending on whether OK or Cancel was clicked:
if(alert('Confirm?') {
// Do stuff
}
However, due to having custom HTML instead of a normal alert I can't do this for two reasons:
I can't return a value from the buttons in the replacement dialogue (click events bound with $.on()) because I have no idea how to.
I can't block program flow with this alert, as far as I know.
I've bound $.on() events to the Cancel and OK buttons in the replacement dialogue which hide the box. These work fine, but the problem I have now is returning a value when a button is clicked, so that execution will halt until an action is taken by the user.
HTML:
<div class="alert background"></div>
<div class="alert box">
<div class="message"></div>
<hr>
<div class="buttons">
<input type="button" name="cancel" value="Cancel">
<input type="button" name="confirm" value="OK">
</div>
</div>
Current JavaScript: (pretty much a carbon copy of the answer in my linked question)
(function () {
nalert = window.alert;
Type = {
native: 'native',
custom: 'custom'
};
})();
(function (proxy) {
proxy.alert = function () {
var message = (!arguments[0]) ? 'null' : arguments[0];
var type = (!arguments[1]) ? '' : arguments[1];
if (type && type == 'native') {
nalert(message);
} else {
// Custom alert box code
console.log(message);
}
};
})(this);
Ideally, I want to be able to put something like this in the // Custom alert box code part:
$('.alert.box input[name="confirm"]').on('click', function() {
// Hide dialogue box - I can do this already
// *** Return `true` or other truthy value from
// alert for use in `if()` statements
});
So that when the OK or Cancel button is clicked, it removes the custom alert box and returns a true or false value from the call to alert(). I can already remove the alert with $.fadeOut() and $.remove(), that's easy. What isn't is knowing how to get the button click events to get alert() (overridden) to return something.
I've tried to be as clear as I can, but I may have missed something out. Please let me know if I have.
The example below shows an approach to creating a custom alert and handling the outcome of the user selection
/*
message = String describing the alert
successCallBack = callback function for when the user selects yes
*/
function exampleAlert(message, successCallback)
{
/*Alert box object*/
var alertBox = document.createElement("div");
/*Alert message*/
var msg = document.createElement("div");
msg.innerHTML = message;
/*Yes and no buttons
The buttons in this example have been defined as div containers to accentuate the customisability expected by the thread starter*/
var btnYes = document.createElement("div");
btnYes.innerHTML= "Yes";
/*Both yes and no buttons should destroy the alert box by default, however the yes button will additionally call the successCallback function*/
btnYes.onclick = function(){ $(this.parentNode).remove();successCallback();}
var btnNo = document.createElement("div");
btnNo.innerHTML= "No"
btnNo.onclick = function(){ $(this.parentNode).remove();}
/*Append alert box to the current document body*/
$(alertBox).append(msg, btnYes, btnNo).appendTo("body");
}
function test()
{
alert("Example alert is working, don't use this test as a replacement test - horrible recursion!")
}
exampleAlert("shoe", test)
This is fairly basic and doesn't allow for additional data to be supplied to the callback function and for that reason is not ideal for production however jQuery's .bind() and similar methods allow for data to be associated with the callback method
It's worth commenting that while the above demonstrates a full implementation of the problem, there are in fact only two lines that actually matter.
btnYes.onclick...
btnNo.onclick...
Since we're achieving the desired result by binding onclick events for true and false respectively, everything else is there to paint the picture.
With that in mind it is possible to effectively turn any container object with at least one sibling into an alert box for eaxmple:
<!-- Example html -->
<div id='a'>
<ul>
<ul>
<li>Something</li>
<li>Something Else</li>
<li id='yesIdentifier'>Something not necessarily suggesting a trigger?</li>
</ul>
</ul>
</div>
As long as your yes / no (if no exists) options destroy the appropriate container a converting a container into an alert box can be handled in a couple of lines of code.
$('#yesIdentifier', '#a').click(
function(){ someCallback(); $(this).closest('#a').remove()});
Neither of the above are exemplary models for implementation but should provide some ideas on how to go about the task.
Finally... do you really need to replace the native alert method? That is, either you're writing the alert calls, in which case you'd know to use your custom method, or you're overwriting default behaviour that you can't guarantee the other developers will be aware of.
Overall recommendation:
I feel the best approach to this would be to create a jQuery plugin which creates the custom alerts on the fly and track callbacks, results and what not within the plugin.
SOliver.
Why don't you just use a confirm box like so.
var c = confirm('Confirm?');
if(c)
{
// Yes clicked
}
else
{
// No clicked
}
Or you could use jQuery UI's dialog confirmation box.
http://jqueryui.com/demos/dialog/#modal-confirmation

Categories

Resources