I'm writing a vb.net program to automate and manage an online game. I'm using the Awesomium webcontrols to display and manipulate the pages of the game.
There is a point where I need to grab the data that's not shown in the source until the user hovers over a certain element, how can I use javascript (Not jquery please) to hover over it programatically until the data I need becomes available and then grabbed?
I apologise if this has been asked before (Which it has but from the perspective of someone who owns the web page) but I have been searching for hours for a solution and cant find anything.
What I've tried to use but failed is:
function findBpDate(){
document.getElementById('tileDetails').children[1].children[0].children[1].children[0].fireEvent('onmouseover');
return document.getElementsByClassName('text elementText')[0].textContent;
}
This returns "undefined" when it calls back to my application, I'm certain I'm pointing to the right DOM elements though.
This is what I want the javascript to "hover" on:
<span class="a arrow disabled">Send troops</span>
Once this element has been "hovered" on, this elements text changes to the text I need to grab:
<div class="text elementText">Beginners protection until 20/07/13 07:51 am.</div>
I've shown above what the element looks like when the mouse "hovers" on the element I need it to, however this changes a lot depending on which element the user hovers over while playing the game, from what i gather it's where the source keeps the text for each tooltip in the game.
So I need a function that will hover over a certain element and then while it's hovering, grab the text from the tooltip text/"text elementText" element.
Try WebView.InjectMouseMove(x, y).
Something like
public Point GetElementPosition(dynamic element)
{
dynamic rect = element.getBoundingClientRect();
using (rect)
{
return new Point(rect.left, rect.top);
}
}
dynamic element = webView.ExecuteJavascriptWithResult("document.getElementById('id')");
Point pos = GetElementPosition(element);
webView.InjectMouseMove(pos.X, pos.Y);
this is 10x easier with js/dom. http://jsfiddle.net/pA2Vd/
Do this...assuming you can get reference to elements somehow using by Id would have been lot easier.
var elm = document.getElementsByClassName('a arrow disabled')[0];
var txt = document.getElementsByClassName('text elementText')[0];
var evt = new Event('mouseover');
elm.dispatchEvent(evt);
var status = txt.innerText;
(helpfuL stuff down) otherwise you need to capture event, detect who fired it, check if that has this class and tag name. Lot of processing.
var txt,spn,status='';
document.getElementByTagName('span').forEach(function(d){
if (d.tagName=="div" && d.className == 'text elementText'){
var txt = d;
}
}
window.onmouseover = function(e) {
var elm = e.target;
if (elm.tagName=="SPAN" && elm.className == 'a arrow disabled') {
status=txt.innerText;
}
}
Related
Environment: Safari 110.0.1, OSX (MacOS) 10.12.6
I am working on an image gallery type of display. There's an element that is loaded with an image by the Javascript; I want that element to have functionality on onmouseenter and onmouseout.
It would appear that I can't add those when I'm creating the img element, because the image is not loaded, and I read (somewhere, lol, it's been a long day) that an element has to be loaded before one can attach functions to it. I did try it in the HTML; no joy.
So I have a timer going, and I am trying to attach it there, but that doesn't work either - the functions are never called.
I tried starting the timer after the page is loaded, but, that doesn't work - the over/out functions still don't fire. The timer is definitely running, that's what forces the redraw if the page scaling changes, and that works. You can see what I want to happen with the mouse over/out by clicking the checkmark below the image.
Here's the page, all the HTML and Javascript code is visible there (lower on the page.) Any insight is appreciated.
The best I've been able to do so far is to get the events to attach to a surrounding div by specifying out in the HTML, where they do pretty much the right thing as far as the div is concerned. But when the mouse is over the image, it is out of the div, so the opposite of what I want happens: the onmouseout fires and the thing I want to have happen over the image goes away.
Is there some reason I can't attach these functions during the timer? Here's the timer code:
function mousingover()
{
console.log('over');
if (dismode == 1) return;
show_image_notes('mypic');
}
function mousingaway()
{
console.log('away');
if (dismode == 0) return;
show_image('mypic');
}
function ticker()
{
// var pic = document.getElementById('mypic'); // get (eventually) ready element
// var eltype = pic.nodeName;
// console.log('eltype:',eltype);
// pic.onmouseenter = function() { mousingover(); }
// pic.onmouseout = function() { mousingaway(); }
// console.log(pic.onmouseout);
// When the display is rescaled, the width of this div changes
// This is used to re-fire the calculation of where the notes go:
var myAnchor = document.getElementById('picdiv');
var xd = myAnchor.offsetWidth;
if (working == 0 && xd != xdim)
{
working = 1;
if (dismode == 1) show_image_notes('mypic');
else show_image('mypic');
xdim = xd;
working = 0;
}
tcounter = tcounter + 1;
if (tcounter > 10 || tcounter < 0) // trying to delay so image has time to load
{
var pic = document.getElementById('mypic'); // get (eventually) ready element
pic.onmouseenter = function() { mousingover(); }
pic.onmouseout = function() { mousingaway(); }
tcounter = 0;
}
}
The console confirms that I am finding the IMG with that ID, which is correct, and also that the functions are attached. They just don't fire.
I'm actively working on this, so the code for the timer will change; the page always displays the code that's in use at the moment.
I'm trying to do this with pure Javascript.
I looked at your HTML, and you have a canvas element in there along with the img element. It looks like the canvas overlays the image, yes? If so, the canvas is going to get the mouse events, and the img won't see them.
I have a flash inside and iFrame and i want to click through iFrame but not through flash. I have seen that, we can click through iFrame via "pointer-events: none;" but it passes everything inside iframe. Now I just want to know, that can we enable or check the mouse click in flash?
I have added an sample for my question. black dots are in a flash swf file and its in iFrame. Now when I click on transparent area then it should be clicked on underneath area that is Label buttons in this case. otherwise black dots should be clicked.
I think it doesn't matter if you are in iframe in this case, if I understand correctly you want a pass-through click from Flash to the underlying HTML page, but only if the click doesn't satisfy some condition (in this case, only if it's not over the black spots).
An approach would be to do it collaboratively between the Flash part and some JavaScript part in the iframe:
Intercept the click in Flash, get coordinates and verify if it's over a black circle
If it is, handle the corresponding logic in Flash, else proceed with the following steps
Pass the coordinates to a JavaScript function already defined in the iframe through Flash's external interface
Finally in the JavaScript you can do something along the lines of How to simulate a click by using x,y coordinates in JavaScript?
To do list :
Use the CSS attribute pointer-events: none; on iframe
Create a invisible div with ID="event-eater" that covers the elements.
Add Javascript below (uses jQuery) to recognizance where click happened
It will call actionscript method ClickPosition and based on returned result do 1 of following
If black area was clicked - Do nothing, click event was created in actionscript
If background was clicked - Temporally hide current element, and recreate click in javascript
Javascript
$('#event-eater').click(function(evt) {
var posX = $(this).offset().left, posY = $(this).offset().top;
var x = Math.abs(Math.round(evt.pageX - posX));
var y = Math.abs(Math.round(evt.pageY - posY));
var result = "["+x+", "+y+"]";
if(document['flashInterface'].ClickPosition(result)=="true"){
$('#event-eater').css({display:'none'});
starter = document.elementFromPoint(evt.clientX, evt.clientY);
$(starter).click();
$('#event-eater').css({display:''});
};
});
Actionscript
package
{
import fl.events.ColorPickerEvent;
import flash.display.MovieClip;
import flash.external.ExternalInterface;
public class Main extends MovieClip {
//set this variable true if background was clicked last, false otherwise
var wasBackgroundClickedLast:Boolean = new Boolean(true)
public function Main() {
//allows JavaScript to access the ClickPosition() function.
ExternalInterface.addCallback("ClickPosition", clickPosition);
}
public function clickPosition(value:String):String{
var va= str.split(",");
simulateClick(Number(va[0]),Number(va[1]));
return wasBackgroundClicked.toString();
}
public function simulateClick(x:Number, y:Number):void
{
var objects:Array = stage.getObjectsUnderPoint(new Point(x, y));
var target:DisplayObject;
while(target = objects.pop()){if(target is InteractiveObject){ break; }}
if(target !== null)
{
var local:Point = target.globalToLocal(new Point(x, y));
var e:MouseEvent = new MouseEvent(
MouseEvent.CLICK, true, false, local.x, local.y);
target.dispatchEvent(e);
}
}
}
}
Small demo : Javascript eventeater with button array below it.
I'm creating a notification system for a game to work similar to how notifications might work in a phone.
The notifications are all created initially, hidden, and later the game is supposed to "activate" certain ones from in-game triggers.
I'm running into problems when trying to keep the notifications separate in terms of their classes. Each notification starts off as a small rectangular box with only the title visible. Upon clicking, the notification expands and the description becomes visible.
Right now, clicking a notification does expand that notification and display its notification, but any other notifications also show their descriptions as well.
Example code:
var NotificationItems = new Array();
scope.registerNotification = function(title, description)
{
//add it to the array
NotificationItems.push(new scope.Application(title, description));
var $NotificationContainer = $("#NotificationContainer");
$NotificationContainer.append('<div class="Notification" title="'+title+'"></div>');
var $thisNotification = $NotificationContainer.children('.Notification[title='+title+']');
$thisNotification.append('<div class="NotificationTitle">'+title+'</div>');
$thisNotification.append('<div class="NotificationDescription">'+description+'</div>');
$(".NotificationDescription").hide();
$thisNotification.click(function()
{
$(this).toggleClass('expanded');
$('.NotificationDescription').slideToggle('slow');
});
}
How can I get the .NotificationDescription to be uniquely recognized for each notification?
You could try the .children() method: jQuery docs for children method
$thisNotification.click(function()
{
$(this).toggleClass('expanded').children('.NotificationDescription').slideToggle('slow');
});
Just find the right one for the clicked element:
$thisNotification.click(function()
{
$(this).toggleClass('expanded');
$(this).find('.NotificationDescription').slideToggle('slow');
});
You can chain the calls if you like:
$thisNotification.click(function()
{
$(this).toggleClass('expanded').find('.NotificationDescription').slideToggle('slow');
});
You might want to try out event delegations.
$('#NotificationContainer > div.Notification').live('click',function()
{
$(this).toggleClass('expanded').find('div.NotificationDescription').slideToggle('slow');
});
This way you only need to attach the event once (on init), and a single event handles all the notifications.
You also should add all your html at one time:
var $NotificationContainer = $("#NotificationContainer");
var $Notification = $('<div class="Notification" title="'+title+'"></div>');
$Notification.append('<div class="NotificationTitle">'+title+'</div>');
$Notification.append('<div class="NotificationDescription">'+description+'</div>');
$NotificationContainer.append($Notification);
notice the subtle difference, we're building the elements in jquery rather than the dom, and append them all at once.
I want to drag and drop images into an aloha editable field.
I am looking at the at.tapo.aloha.plugins.Image plugin which seems great.
However, i need to adapt this plugin in order to work with thumbnail. I drag the thumbnail and when I drop it into the aloha editable, the html code is modified on the fly in order to use the real image.
GENTICS.Aloha.EventRegistry.subscribe(GENTICS.Aloha, 'editableCreated', function(event, editable) {
var the_obj = editable.obj;
jQuery(editable.obj).bind('drop', function(event){
var e = event.originalEvent;
var files = e.dataTransfer.files;
var count = files.length;
if (count < 1) {
var node = e.dataTransfer.mozSourceNode;
if (node.tagName === 'IMG') {
var html = '<img ....>'; //build the real image html code
/// The current selection but I want the drop position
var range = GENTICS.Aloha.Selection.getRangeObject();
if (!jQuery.isEmptyObject(range)) {
GENTICS.Utils.Dom.insertIntoDOM(jQuery(html), range, the_obj);
}
return false;
}
return true;
}
}
It works ok when something is selected in the aloha field. I can get a range and insert the html into the DOM at the selection position.
However, I would like to get a range object that correspond to the place where my image is dropped. How to do that?
Thanks in advance for ideas.
There isn't an easy way that I know of to do this in general. You could obtain pixel coordinates for the drop point (possibly from a mousemove event) and then attempt to get a range for that point. For that task, the answer to the following question sums it up nicely:
Creating a collapsed range from a pixel position in FF/Webkit
Tim Down showed me that there is no easy way and I finally used a workaround:
GENTICS.Aloha.EventRegistry.subscribe(GENTICS.Aloha, 'editableCreated', function(event, editable) {
var the_obj = editable.obj;
jQuery(editable.obj).bind('drop', function(event){
setTimeout(function () {
//at this point the html is updated and can be postprocessed
//in order to turn thumbnails into the real image
//force the focus in order to make sure that the editable is activated
//this will cause the deactivated event to be triggered, and the content to be saved
the_obj.focus();
}, 0);
});
});
I want JavaScript code to detect the mouse cursor type.
For example when the cursor hovers in <textarea> it changes from default to text.
How would I go about detecting this?
You could do this, but its not pretty, and will probably be quite slow depending on how many elements you have on your page.
$('*').mouseenter(function(){
var currentCursor = $(this).css('cursor') ;
//do what you want here, i.e.
console.log( currentCursor );
});
You can detect the cursor type using JavaScript
like
<input id="sample_text" name="one" type="text" value="Sample Text" />
and the JavaScript code should look something like this
$('input[id=sample_text]').click( function() {
alert("test");
var ctl = document.getElementById('sample_text');
var startPos = ctl.selectionStart;
var endPos = ctl.selectionEnd;
alert(startPos + ", " + endPos);
});
you can also look at this Jsfiddle for Js Cursor Detection
the above is the Jquery code written , you can also use the Vanilla JS for that you just need to change it to
<input id="sample_text" name="one" type="text" value="Sample Text" onclick="detect_cursor()" />
and the JavaScript should look something like this
function detect_cursor() {
alert("test");
var ctl = document.getElementById('sample_text');
var startPos = ctl.selectionStart;
var endPos = ctl.selectionEnd;
alert(startPos + ", " + endPos);
};
I have a nice jQuery Extension perfect for this type of thing at this gist:
https://gist.github.com/2206057
To use it just do something like:
$("#eleID").cursor(); // will return current cursor state for that element
$("#eleID").cursor("pointer"); // will change ele cursor to whatever is ""
$("#eleID").cursor("clear"); // will change ele cursor to default
$("#eleID").cursor("ishover"); // will return boolean of if mouse is over element or not
$("#eleID").cursor("position"); // will return cursor's current position in "relation" to element
also
$.cursor("wait") // will change document cursor to whatever is ""
$.cursor($("#eleID"), "wait"); // same as $("#eleID").cursor("wait");
$.cursor("position") // will return current cursor position
should also mention, if you submit multiple elements like $("#eleID1, .elementsWiththisClass") for "position" and "isHover" then it will return an Array containing objects like:
var poses = $("#eleID1, .elementsWiththisClass").cursor("position") // will equal
poses[0] = {
ele: e.fn.e.init[1], // the jquery element
x: XXX, // where XXX is the cursors current position in relation to element
y: XXX
}
poses[1] = { // ...and so on and so forth for each element
I think you can read the cursor css property just like you can set it, but you have to do this from a specific element because AFAIK there's no way to just read the cursor type from the window or document object. Following this logic, to get the current cursor type you would have to find the current element the mouse is over and read its cursor css. However, you'd constantly have to check to see if the cursor changed, which is slow and error prone (As a rule you should almost always try to try to put your code in an event handler to react to something instead of constantly checking if its happened yet and putting your code in that function its more logical, efficient, robust, and clear.)
But the idea of detecting the cursor type still fascinates me, and if anyone knows how I'd love to hear about it. :D
As an alternate solution, rather than reading the cursor type, why don't you just set an event handler for when it enters an element that would change it? This would be a lot less error prone and probably more direct, because I don't think you care so much about the cursor, but if the mouse has entered a specific element.
$("#textbox").mouseover( function() {
//I know the cursor has changed because it is now in a textbox
});
As suggested here, using getComputedStyle worked for me.
const onMouseOver = function (e) {
var cursor = getComputedStyle(e.target).cursor;
console.log({ cursor });
};
document.addEventListener("mouseover", onMouseOver, false);
Although this does not help detect the exact cursor type when cursor is set to auto, we can at least use it when cursor is set to something other than auto.