ClientListener for RichCommandButton - javascript

I am required to call a method when mouse hovers onto a RichCommandButton programmatically.
private UIComponent ImageButton(UIComponent parent){
RichCommandButton img = new RichCommandButton();
String imagestyle = "width:120pt; height:120.0pt;margin:10.0pt;";
img.setInlineStyle(imagestyle);
ClientListenerSet set = img.getClientListeners();
if (set == null) {
set = new ClientListenerSet();
}
set.addListener("click", "handle");
img.setClientListeners(set);
parent.getChildren().add(img);
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
adfFacesContext.addPartialTarget(parent);
return img;
}
and in my JSPX page,
<f:facet name="metaContainer">
<af:resource type="javascript">
function handle(evt){
var source = evt.getSource();
AdfLogger.LOGGER.logMessage(AdfLogger.SEVERE, 'gangangan');
evt.cancel();
}
</af:resource>
</f:facet>
It never goes into this function (checked For log message in console on Chrome->Inspect element). Please let me know how I can invoke a method by mouseOver.

Do you use img.setClientComponent(true) in your method? If your JavaScript needs this component then it needs to be present on the client side too.

I think you should add your client listener to the mouseOver event instead of click:
set.addListener("mouseOver", "handle");
You can check the rest of the available client events in this page.

Related

JavaScript last element of HTML collection not defined

I am trying to create a bookable product, where upon selected (= selectbox) a room type, the picture changes to that specific room with good old javascript.
the interesting part is that it works for the first element of the HTML collection, but the last element is giving an undefined and makes it impossible to override.
I am not getting why that is. I tried via the console log to view what I am missing, but I see nothing problematic.
HTML collection:
0: <a href="https://staging.deloftli…09/Steck-coachruimte.jpg" hidefocus="true" style="outline: currentcolor none medium;">​
1: <img class="zoomImg" role="presentation" alt="" src="https://staging.deloftli…09/Steck-coachruimte.jpg" style="position: absolute; top:…none; max-height: none;">
I have the following script:
<script id="bookingschanges">
var activities = document.getElementById("wc_bookings_field_resource");
var image = document.getElementsByClassName("woocommerce-product-gallery__image")[0].children[0].firstChild;
var zoompic = document.getElementsByClassName("woocommerce-product-gallery__image")[0].children[1];
activities.addEventListener("click", function() {
var options = activities.querySelectorAll("option");
});
activities.addEventListener("change", function() {
if(activities.value == "1949")
{
image.src = "https://staging.deloftlisse.nl/wp-content/uploads/2021/09/Podkas.jpeg";
image.srcset = ""
zoompic.scr = "https://staging.deloftlisse.nl/wp-content/uploads/2021/09/Podkas.jpeg";
}
console.log(image);
console.log(zoompic);
});</script>
The first element (image) is correct, the second element (zoompic) gives undefined.
To see it live, go to https://staging.deloftlisse.nl/product/vergaderruimte-huren/ and check the console log.
What am I missing here?
Variable zoompic is not defined at the time the variable is declared (its called before the element is created on loading, debug the page and refresh it to see) you will need to use an onload event listener.
https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
As someone else has suggested it would be better to call the image change function in the original javascript to change the image that is selected and you will avoid any issues. This might not be easy though if it is an external library.
EDIT: Added an example of onLoad
window.addEventListener('load', (event) => {
var activities = document.getElementById("wc_bookings_field_resource");
var image = document.getElementsByClassName("woocommerce-product-gallery__image")[0].children[0].firstChild;
var zoompic = document.getElementsByClassName("woocommerce-product-gallery__image")[0].children[1];
activities.addEventListener("click", function() {
var options = activities.querySelectorAll("option");
});
activities.addEventListener("change", function() {
if (activities.value == "1949") {
image.src = "https://staging.deloftlisse.nl/wp-content/uploads/2021/09/Podkas.jpeg";
image.srcset = "https://staging.deloftlisse.nl/wp-content/uploads/2021/09/Podkas.jpeg 768w";
zoompic.src = "https://staging.deloftlisse.nl/wp-content/uploads/2021/09/Podkas.jpeg";
}
console.log(image);
console.log(zoompic);
})
});

Sending a chunk of HTML to another URL using postMessage()

Objective: Copy a chunk of HTML and send it to a website on another domain.
My problem: The website I'm working on and the website in the iframe are on different domains. I own both of them and have set the Access-Control-Allow-Origin to allow the websites to communicate to each other. However, I can't seem to pass the HTML chunk to the parent window.
I've tried parent.window.postMessage(chunk, http://www.parent-page.com) (chunk is the chunk of HTML code) but I get this error:
Uncaught DataCloneError: Failed to execute 'postMessage' on 'Window': An object could not be cloned.
I have also tried to use ajax to send a PUT request to the parent window but, I get a 404 error that it cannot find the parent window. *I am running the parent window from my local server.
My Question: Can anyone tell me the best way to send an object, containing HTML code, from an iframe to the parent window given that the two websites are NOT on the same domain?
EDIT: I removed the stuff about a skeleton object as that was out of the scope of the question I was really trying to ask.
Here is what I wrote to solve this. Any constructive criticism is welcome.
Code on parent window's website:
//send a message to the website in the iframe
$("#frame").on("load", function (event) {
var viewContainer = $('#element-highlight');
var iframe = document.querySelector('iframe');
var receiver = iframe.contentWindow;
var location = 'http://www.child-website.com';
event.preventDefault();
receiver.postMessage("sendStructure",location);
});
//listen for a response
window.addEventListener('message', function(event) { //event = onmessage event object
if (~event.origin.indexOf('http://ccook.oegllc.com')) { //indexOf returns a -1 if the searchValue is not found
var structure = event.data;
var container = document.getElementById("element-highlight");
container.innerHTML = structure;
}
}
<script src="../jquery/3.0.0/jquery.min.js"></script>
<body>
<div id="frame-container">
<iframe id="frame" src="http://www.main-site.com" frameborder="0"></iframe>
<div id="element-highlight">
<!-- Store Skeleton Copies here -->
</div>
</div>
</body>
Code on the website that is shown in the iframe:
I can't get the case statement below to look any better.
//listen for command from main-site.com
window.addEventListener('message', function(event) { //event = onmessage event object
if (~event.origin.indexOf('http://www.main-site.com')) { //indexOf returns a -1 if the searchValue is not found
switch(event.data){
case "sendStructure":
var structure = getStructure(),
tempNode = document.createElement("div");
structure.appendTo(tempNode); //appends structure to html document
var str = tempNode.innerHTML; //creates a serilized version of the structure
parent.window.postMessage(str, event.origin); //send structure string to main-site.com
break;
//I reccomend using a case statement if the two sites will be sending more than one message to each other
default:
sendError();
}
}
});
function getStructure(){
//this method creates a skeleton of the course page you are on
//returns a skeleton object
console.log("compiling structure");
var viewFrame = $('body').contents(); //<-change 'body' to whatever element you want to copy
var visible = viewFrame.find('*:not(html body)').filter(':visible');
var overlayElements = visible.map(function (i, el) {
var el = $(el);
var overlayEl = $('<div>');
overlayEl.addClass('highlight').css($.extend({
position: 'absolute',
width: el.outerWidth(),
height: el.outerHeight(),
'z-index': el.css('z-index')
}, el.offset()));
return overlayEl.get();
});
return overlayElements;
}
function sendError(){
console.log("main-website's request could not be understood");
}

What's the proper way to implement Porthole.js for resizing an iframe based on content height?

I am trying to use Porthole.js (http://ternarylabs.github.io/porthole/) to pass the height of an iframe's content to its parent (so the parent can resize the iframe to "fit" the contents)... but I can't get it to work.
The parent (on abc.com):
<script src="porthole.min.js"></script>
<script type="text/javascript">
var guestDomain = 'xyz.com';
function onMessage(messageEvent) {
if (messageEvent.origin == "http://" + guestDomain) {
if (messageEvent.data['newHeight']) {
el = document.getElementById('iframe-name-here');
newHeightvar = (messageEvent.data['newHeight'],60);
window.alert("PARENT RECEIVED VALUE (+60): "+newHeightvar);
el.setAttribute('height', newHeightvar);
};
};
};
var windowProxy;
// register proxy window url and iframe name
var proxy = new Porthole.WindowProxy("http://xyz.com/proxy.html", "iframe-name-here");
// register an event handler to receive messages
proxy.addEventListener(onMessage);
</script>
The iframe (on xyz.com):
<script src="js/porthole.min.js"></script>
<script type="text/javascript">
$(document).ready(function($) {
var proxy = new Porthole.WindowProxy("http://abc.com/proxy.html");
var heightVal = $(document).height();
window.alert("CHILD SENT VALUE: "+heightVal);
proxy.post({"newHeight" : heightVal});
});
</script>
I am unsure how to test better to see if the data is being pushed from iframe to parent. The alerts fire but the parent alert isn't giving me the value of the passed data.
Basically, I want to receive the iframe's content size (messageEvent.data['newHeight']), add 60px to it, and set the iframe's height accordingly. Where am I going wrong? D:
Use window.load instead of ready event. see doc
var windowProxy;
window.onload=function(){
// Create a proxy window to send to and receive
// messages from the iFrame
windowProxy = new Porthole.WindowProxy(
'http://other-domain.com/proxy.html', 'guestFrame');
// Register an event handler to receive messages;
windowProxy.addEventListener(onMessage);
};

jQuery change page's title when user in a different tab

I have live chat on my page. I want to change the title (with something moving like in omegle.com) when a new message is received and the user is not in the same tab as the live chat. When the user returns to the tab, the title would return to normal.
I guess it should be done by jQuery. Do you know any plugins or how can I do that?
Title can only be edited like so:
document.title = "blah";
So you could do:
var origTitle = document.title;
document.title = "You have ("+x+") new messages - "+origTitle;
To make it flash you would have to do something with setTimeout();
var origTitle = document.title;
var isChatTab = false; // Set to true/false by separate DOM event.
var animStep = true;
var animateTitle = function() {
if (isChatTab) {
if (animStep) {
document.title = "You have ("+x+") new messages - "+origTitle;
} else {
document.title = origTitle;
}
animStep = !animStep;
} else {
document.title = origTitle;
animStep = false;
}
setTimeout(animateTitle, 5000);
};
animateTitle();
try
$('title').text("some text");
Update
Apparantly, in IE, $('title')[0].innerHTML returns the content of the <title> tag, but you can't set it's value, except using document.title. I guess this should be an improvement to the jQuery API, since $('title')[0] does return a DOMElement (nodeType = 1)...
$('title').text('your title') suffices.
To see if you're taking the right path, simply use IE's developer toolbar (F12) and go to console and write $('title'), you should see [...] in console. This means that $('title') is an object and it works up to here. Then write typeof $('title').text, and you should see function as the result. If these tests are OK, then your IE is broken.

How to change event handlers dynamically with JavaScript?

I'm pretty new to anything AJAX and ran into the following problem. I hope someone here is able to help me out. I'm sure it's an easy fix but I just don't see it :(
What I'm trying to do is change the onmouseover and onmouseout events dynamically for the element, here are the relevant bits of code:
The HTML Element (notice there are multiple of these, hence the dynamic part of their id)
<?
if (ownsgame($id, $userid)) {?>
<a><img src="images/collection/got.gif" id="ownedimage<?=$id?>" title="<?=$itemtitle?> (<?=$platformdisplay?>) is in your collection" alt="You own this game" align="center" width="62" height="22" onclick="changeOwned('<?=$id?>')" onmouseover="changeImageSrc('ownedimage<?=$id?>', 'images/collection/del.gif')" onmouseout="changeImageSrc('ownedimage<?=$id?>', 'images/collection/got.gif')"/></a>
<? } else { ?>
<a><img src="images/collection/add.gif" id="ownedimage<?=$id?>" title="Add <?=$itemtitle?> (<?=$platformdisplay?>) to your collection" alt="You do not own this game" align="center" width="62" height="22" onclick="changeOwned('<?=$id?>')" onmouseover="changeImageSrc('ownedimage<?=$id?>', 'images/collection/add.gif')" onmouseout="changeImageSrc('ownedimage<?=$id?>', 'images/collection/add.gif')"/></a>
<?} ?>
The JavaScript function:
function changeImageSrc(id, src) {
document.getElementById(id).src = src;
}
The (relevant) AJAX code:
var http = createRequestObject();
var jsid = "";
function changeOwned(id) {
http.open('get', 'changeowned.php?id=' + id + '&user=<?=$userid?>');
jsid = id;
http.onreadystatechange = processResponse;
http.send(null);
}
function processResponse() {
if((http.readyState == 4) && (http.status == 200)){
var response = http.responseText;
var elementid = 'ownedimage' + jsid;
var element = document.getElementById(elementid);
if (response == "1") {
image = "images/collection/got.gif";
alt = "you own this game";
mouseoverstr = 'images/collection/del.gif';
mouseoutstr = 'images/collection/got.gif';
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/add.gif')}, false);
element.removeEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/add.gif')}, false);
} else {
image = "images/collection/add.gif";
alt = "add this game to your collection";
mouseoverstr = 'images/collection/add.gif';
mouseoutstr = 'images/collection/add.gif';
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/got.gif')}, false);
element.removeEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/del.gif')}, false);
}
element.src = image;
element.alt = alt;
element.addEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, mouseoverstr)}, false);
element.addEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, mouseoutstr)}, false);
}
}
It seems to work fine at first but produces some weird behaviour. The referenced PHP works fine and produces the correct response. The srcand alt of the image get changed as well. In fact, it first looks like the new mouseover/out work too. But when you click on more than one image on the site (which have different IDs) they suddenly start influencing each other. When you mouseover over one, the other changes its image aswell. Why is this happening? I really am clueless as the jsid part is fine and I don't understand why the mouseover suddenly changes two images. It looks as if multiple eventhandlers for different IDs are assigned to the same image element. No idea why that is though. I hope some of you with more AJAX knowledge can help me here, quite frustrated :(
A couple of things there: :-)
1) addEventListener and removeEventListener work with the newer DOM2 handler chain, which is completely separate from the older "DOM0" style (the onXYZ attributes). So you can't remove a handler via removeEventListener that you've originally assigned via an onXYZ attriubte. To do that, assign "" to the attribute's reflected property.
element.onmouseover = "";
2) When you use removeEventListener, you must pass in the same function reference that you used originally. So this will never remove anything:
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/got.gif')}, false);
...because it creates a brand new function to pass into removeEventListener, and since that function isn't on the event handler chain, the call is ignored.
I'd probably approach the problem by having a single event handler, but then changing the data it works with. You can do that by storing the alternate image URLs on the actual element itself, using a data-xyz attribute (say, data-oversrc and data-stdsrc or some such). Then your two functions (one for mouseover, one for mouseout) that change the URL based on the image:
function handleMouseOver() {
this.src = this.getAttribute('data-oversrc');
}
function handleMouseOut() {
this.src = this.getAttribute('data-stdsrc');
}
I'd drop the onXYZ handlers from the elements entirely, and replace them with a one-time addEventListener (attachEvent on IE) that assigns both of those.
data-xyz attributes, like all custom attributes, are invalid in HTML4 and earlier. As of HTML5, they validate, and since no major browser has a problem with invalid attributes anyway, you can start using them right away.
Off-topic #1: These days, I usually recommend using a JavaScript library to smooth over browser differences and implement useful functionality for you. For instance, your code using addEventListener and removeEventListener will fail on IE prior to IE9 because it simply doesn't have those methods. If you use a library like jQuery, Prototype, YUI, Closure, or any of several others, they'll deal with that stuff for you so you can focus on your own value-add.
Off-topic #2: The mouseover event happens repeatedly when the mouse is passing over the element, and both it and mouseout bubbles up the DOM. This means that for hover effects like yours, if you can't use CSS (and you can't on IE6), you're better off using the mouseenter and mouseleave events, most of the time. But those are IE-specific events not supported by most other browsers. Enter any decent JavaScript library. :-) They'll emulate mouseenter and mouseleave on browsers that don't support them directly. Of the list above, I know for certain that jQuery and Prototype do that; I'd be surprised if the others don't have similar functionality.
The issue is the removeEventListener, it's not working like you think it is. What's happening is when you do this:
element.removeEventListener('mouseout',function(){/* handlers */},false);
That function() { } is a new anonymous function you just created, not the existing one on the element as a listener...so when it goes to remove that listener, it just isn't there, because that was a different anonymous function (even if it had the exact same code, it's a different reference) that you assigned via addEventListener.
There are a few work-arounds for this, given that you're making AJAX requests I'm assuming you're not making hundreds/thousands here, so you could just store the handlers you assign for removing them later, like this:
var http = createRequestObject();
var jsid = "";
var handlers = {};
function changeOwned(id) {
http.open('get', 'changeowned.php?id=' + id + '&user=<?=$userid?>');
jsid = id;
http.onreadystatechange = processResponse;
http.send(null);
}
function processResponse() {
if((http.readyState == 4) && (http.status == 200)){
var response = http.responseText,
elementid = 'ownedimage' + jsid,
element = document.getElementById(elementid),
image, alt, mouseoverstr, mouseoutstr;
if (response == "1") {
element.src = "images/collection/got.gif";
element.alt = "you own this game";
mouseoverstr = 'images/collection/del.gif';
mouseoutstr = 'images/collection/got.gif';
} else {
element.src = "images/collection/add.gif";
element.alt = "add this game to your collection";
mouseoverstr = 'images/collection/add.gif';
mouseoutstr = 'images/collection/add.gif';
}
//Create a holder if this is the first time for this elementid
if(!handlers[elementid]) handlers[elementid] = {};
//Remove old handlers
element.removeEventListener('mouseover', handers[elementid].mouseover, false);
element.removeEventListener('mouseout', handers[elementid].mouseout, false);
//Store new handlers
handlers[elementid].mouseover = function(){changeImageSrc('ownedimage' + jsid, mouseoverstr)};
handlers[elementid].mouseout = function(){changeImageSrc('ownedimage' + jsid, mouseoutstr)};
//Add hew handlers as listeners
element.addEventListener('mouseover', handers[elementid].mouseover, false);
element.addEventListener('mouseout', handers[elementid].mouseout, false);
}
}

Categories