I'm building a visualization for the Knight's tour problem.
I'm using chessboard-element (Which is basically a modern version of the chessboard.js library), and it has been smooth until I've reached this barrier.
My issue is: I need a way to show markup that indicates the number of the last-played move.
Image of the application
As you can see in the picture above, when the knight is moved manually by the user, or if the move is indicated by the Warnsdorff's rule, I need the resulted square to be marked up with the number of the move Image describing seemingly the desired behavior.
My current approach to this problem is by accessing the element in the DOM using its id and attaching the desired markup for it, but the issue is: even if I tried to do so, it will result in the knight not showing for some reason A picture showing the weird behavior.
const targetId = "square-" + target
const targetEl = Array.from(this.board.shadowRoot.querySelector("[part~='board']").children).find(({ id }) => id === targetId)
targetEl.innerHTML += `<h4>${this.takenSpots.length}</h4>`
Is there's an API in the chessboard-element library that I can use to accomplish the desired output?
If not, is there a css-hack (or similar) around this problem?
If not, is there any other similar chessboard libraries that I can use to solve this issue?
If not, how do you suggest to approach this problem?
Related
I want to take the logo of google.com and rotate it, not big deal and nothing really important, I just wanna learn JS in a fun way.
When I use the select element tool (Ctrl+Shift+c in chrome) I get that logo's id is "logo", so I'm trying this way:
const logo = document.getElementById("logo");
But I get this everytime I try:
undefined
I'd appreciate any help, TY <3
You need to target it's class, id or an attribute. Assuming you're talking about Google's default search homepage, the class seems to be using a dynamic value (you can still target using that value but your code will not work if you try to run it again when the values have changed) so you could target it's alt attribute instead and use the transform rotate() css property on it like this:
const logo = document.querySelector('img[alt="Google"]');
logo.style.transform = "rotate(180deg)";
The above two lines should rotate the Google logo if you run it in the browser console.
I'm assuming you entered that in the JS console.
The result of the const logo = ... statement is undefined, but that doesn't mean the const didn't get assigned (though in case the element doesn't exist, then logo did get assigned undefined...).
If the element does exist and you follow up with logo.style.transform = 'rotate(90deg)', it should work out fine.
As an aside, document.querySelector("img[alt=Google]") may be more bullet-proof for Google's front page.
See:
I am trying to use Selenium to click on a ::after pseudo element. I realize that this cannot be done through the WebDriver directly, but cannot seem to figure out a way to do so with Javascript.
Here is what the DOM looks like:
<em class="x-btn-split" unselectable="on" id="ext-gen161">
<button type="button" id="ext-gen33" class=" x-btn-text">
<div class="mruIcon"></div>
<span>Accounts</span>
</button>
::after
</em>
This is what the above element looks like. The Left hand side of the object is the 'button' element and the :after element is the right hand side with the arrow which would bring down a dropdown menu when clicked. As you can see that the right hand side has no identifiers whatsoever and that is partially what is making this difficult to do.
I have seen these two links in stackoverflow and have attempted to combine the answers to form my solution, but to no avail.
Clicking an element in Selenium WebDriver using JavaScript
Locating pseudo element in Selenium WebDriver using JavaScript
Here is one my attempts:
string script = "return window.getComputedStyle(document.querySelector('#ext-gen33'),':before')";
IJavaScriptExecutor js = (IJavaScriptExecutor) Session.Driver;
js.ExecuteScript("arguments[0].click(); ", script);
In which I get this error:
System.InvalidOperationException: 'unknown error: arguments[0].click is not a function
(Session info: chrome=59.0.3071.115)
(Driver info: chromedriver=2.30.477700 (0057494ad8732195794a7b32078424f92a5fce41),platform=Windows NT 6.1.7601 SP1 x86_64)'
I've also tried using the Actions class in Selenium to move the mouse in reference to the left hand side, similar to this answer as well. I think it may be because I don't know what the offset is measured in and the documentation doesn't seem to give any indication. I think it is in pixels??
Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).MoveByOffset(235, 15).Click().Build().Perform();
This attempt seems to click somewhere as it gives no errors, but I'm not really sure where.
I'm attempting to automate Salesforce (Service Cloud) in c# if that helps.
Maybe someone can offer a solution?
I've encounter the same problem while writing Selenium tests for Salesforce and managed to solve it by direct control over mouse using Actions.
Wrapper table for this button has hardcoded width of 250px, and you have spotted that. To locate where the mouse is, you can use contextClick() method instead of Click(). It simulates right mouse button so it will always open browser menu.
If you do:
Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).ContextClick().Build().Perform();
you will spot that mouse moves to the middle of the WebElement, not the top left corner (I thought that it does too). Since that element width is constant, we can move mouse just by 250 / 2 - 1 to the right and it will work :)
code:
Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).MoveByOffset(124, 0).Click().Build().Perform();
For those who are trying to do this in Python, the solution is below:
elem= driver.<INSERT THE PATH TO ELEMENT HERE>
ActionChains(driver).move_to_element_with_offset(elem,249,1).click().perform()
Basically here I'm finding my element in the DOM and assigning to a WebElement. The WebElement is then passed the method move_to_element_with_offset as a param.
I got the px values for the element from developer tools.
PS: use this import- from selenium.webdriver.common.action_chains import ActionChains
You can read more about Action chain class and its method move_to_element_with_offset here: http://selenium-python.readthedocs.io/api.html.
Hope this helps.
Maciej'a answer above worked with WebDriver, but not with the RemoteWebDriver (Selenium 3.12.0) against Firefox V.56. We needed a solution that worked for both local and remote. Ended up using keyboard shortcuts to invoke the Navigation Menu drop down. As an added benefit, this also removes the need to use offsets.
String navigationMenuDropdownShortcutKeys = Keys.chord(Keys.ESCAPE, "v");
new Actions(driver)
.sendKeys(navigationMenuDropdownShortcutKeys)
.perform();
Im going to provide an alternative that may work for some scenarios, at least it did the trick for me, and is relatively easy to implement in any language using selenium via a JS script.
In my scenario there was an ::after pseudoelement containing the functionality of a button. This button was contained in a position relative to another element under it.
So I did the following:
Get the element that I can, in this question scenario would be that span.
Get the coordinates of the element.
Calculate the coordinates realtive to that element of the pseudoelement you want to click.
Click on those coordinates.
This is my code using perl, but I'm sure you can do the same in any language:
my $script="
function click_function(x, y)
{
console.log('Clicking: ' + x + ' ' + y);
var ev = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true,
'screenX': x,
'screenY': y
});
var el = document.elementFromPoint(x, y);
el.dispatchEvent(ev);
}
var element = document.getElementById('here_put_your_id'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?
document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;
console.log('Coordiantes: ' + elementLeft + ' ' + elementTop)
click_function(elementLeft*1.88, elementTop*1.045) // here put yor relative coordiantes
";
$driver->execute_script($script);
After going through numerous article and the blogs I figured out the way to determine how to detect the Pseudo element in the DOM in the Selenium. And validate based on the certain conditions if it is present or no.
Step 1
Find the path to the parent element which consist the pseudo element and pass under the findElement as shown below
WebElement pseudoEle = driver.findElement(path);
Step 2
String display = ((JavascriptExecutor)getWebDriver()).executeScript("return window.getComputedStyle(arguments[0], ':after').getPropertyValue('display');",pseudoEle).toString();
In the above line of code pass the desired Pseudo code in the place of ":after" (In my case I was looking for 'after') and the property value which is changing based on the pseudo code is present or no (In my case it was 'display').
Note: When the pseudo element was present javascript code return 'Block' which in turn I saved in the display field. And use it according to the scenario.
Steps to determine the right property value for your case
Inspect the element.
Navigate to the parent element of the pseudo code.
Under the Styles tab figure out the field(Green in color) whose value change when the pseudo code is present and when not present.
I am sure this would help you to the great extent. Kindly like and support, would encourage me to post more solutions as such.
Thanks!
Warning: not duplicate with existing questions, read through
I know I can have an event listen on changes on an contenteditable element.
What I would like is to be able to know what the changes are.
For example:
inserted "This is a sentence." at position X.
deleted from position X to Y.
formatted from X to Y with <strong>
Is that possible? (other than by doing a diff I mean)
The reason for this is to make a WYSIWYG editor of other languages than HTML, for example Markdown.
So I'd like to apply the changes to the Markdown source (instead of having to go from HTML to Markdown).
You may be able to do something with MutationObservers (falling back to DOM Mutation events in older browsers, although IE <= 8 supports neither) but I suspect it will still be hard work to achieve what you want.
Here's a simple example using MutationObservers:
http://jsfiddle.net/timdown/4n2Gz/
Sorry, but there is no way to find out what the changes are without doing a diff between the original content and the modified one when changes occur.
Are you looking for this
var strong=document.createElement("strong");
var range=window.getSelection().toString().getRangeAt(0);
range.surroundContents(strong);
this was for third part
You just need to select what you want to surround using real User interaction.
If you wanna do it dynamically
var range=document.createRange();
range.setStart(parentNode[textNode],index to start[X])
range.setEnd(parentNode[textNode],index to end[Y])
range.surroundContents(strong);
For 2nd Part
range.deleteContents()
1st part can be done by using simple iteration
var textnode=// node of the Element you are working with
textnode.splitText(offset)
offset- position about which text node splitting takes place[here==X]
Two child Nodes have been created of the parent editable Element
Now use simple insertBefore() on parent editable Element Node.
hope you will find it useful
The API you're looking for does not exist, as DOM nodes do not store their previous states.
The data / events you're wishing to get back are not native implementations in any browser Ive come across, and I struggle to think of a datatype that would be able to generically handle all those cases. perhaps something like this:
function getChanges() {
/* do stuff here to analyse changes */
var change = {
changeType : 'contentAdded',
changeStart : 50, /* beginning character */
changeContent : 'This is a sentence'
}
return change;
}
Since you're trying to get custom events / data, you're probably going to need a custom module or micro-library. Either way, to look at the changes of something, you need somehow be aware of what has changed, which can only be done by comparing what it was to what it is now.
I have created the following image gallery.
http://jsfiddle.net/sfiddle/Nf7yR/7/
I think the thing is, that even though I can get a hand on the paragraphs css, the currentIndex won't update, i.e. an event listener seems to be missing.
var thumb = document.getElementById("thumb");
myParagraphs = thumb.getElementsByTagName("p");
console.log(myParagraphs[1]);
function thumby(){
$(myParagraphs[currentIndex]).css("background-color", "red");
}
thumby();
The thing is that I can not manage to link the image index with the index of the pagination dot (which has a normal p tag).
I want to code it in that way that if the first picture is displayed the first dot is red, if the second image is displayed the second ...
How could I approach this?
Thanks for any good advice as I invested a few hours already but can not get my head around it.
PS: no, I want no plugin or ready made imagegallery, I want my approach to work :-)
You made a function thumby() but you are calling it only once (during script start). You just need to call it when you change currentIndex. Here you have fixed code: http://jsfiddle.net/Nf7yR/10/ (I commented my edits).
BTW your code looks terrible. You should indent it properly to make it easier to read :)
I've got a pretty simple problem whose solution turns out not to be that simple at all.
I want to add images in front of each option of a selectfield. To be more accurate, I want to add images to the picker it triggers, and also to the selectfield's current value.
For the sake of simplicity, I'll create a little example:
Let's say, you want a user to choose between one of the four playing card suits Diamonds, Hearts, Spades and Clubs. To support visual recognition, you want to prepend the corresponding symbol to each suit name, so it could look something like this:
My first choice of a sencha touch component, that enables selecting from a given set of options naturally was selectfield. Unfortunately, it only seems to be able to display pure text, and nothing more. After digging into the sencha touch sources, I finally came up with half a solution. Basically, I pass the selectfield a custom defaultPhonePickerConfig, in which the corresponding picker(that is used by the selectfield to display the options) gets assigned a custom itemTpl. The itemTpl does the rest, namely adding some html to display the image:
defaultPhonePickerConfig: {
listeners: {
initialize: function() {
var slots = this.query('pickerslot');
Ext.each(slots, function(slot) {
slot.setItemTpl('<img src="someImage.jpg"> {text}');
});
},
change: function() {
// reconstruct the selectfield's change handler,
// since it gets overwritten
var iconSelect = Ext.Viewport.query('#IconSelect')[0];
iconSelect.onPickerChange.apply(iconSelect, arguments);
}
}
}
A working fiddle for this solution can be found here.
My solution isn't that bad, but there's a slight cosmetical problem, that's just not acceptable to me: The icons are only displayed in the picker (lower part of the screenshot above), but not the selectfield itself (upper, grayed out part) when the option was selected. And there seems to be no good way to add an icon to the selectfield's current value aswell.
And that's the main concern of my question: What good way is there to add an icon to both the picker's options and also to the selecfield's current value? Do I maybe just have to add relatively little code to my existing solution or should I take a whole nother approach?
Every contribution is appreciated. Thank you!
Update:
After some hacking around, I found a way (an ugly one) to prepend an icon to the selectfield itself. It is mostly based on brutal HTML DOM manipulation: I now also define event handlers for the selectfield itself (change and painted). On initialization and every time the value is changed, my handlers search the generated DOM for the underlying <input> and mess around with it. (That bad boy is probably the reason why we can't assign HTML in the first place, since the framework changes its value attribute. And value on the other hand can only contain plain text.)
This is how I define the selectfield's listeners:
listeners: {
change: function () {
var pickerDOM = document.querySelector('#' + this.getId() + ' input[name="picker"]');
PickerIcons.app.prependIconToSelectfield(arguments[1], pickerDOM);
},
painted: function () {
// Initialize an icon on creation
var pickerDOM = document.querySelector('#' + this.getId() + ' input[name="picker"]');
PickerIcons.app.prependIconToSelectfield(this.getValue(), pickerDOM);
}
}
The corresponding function prependIconToSelectfield() just defines some CSS:
prependIconToSelectfield: function (optValue, domElement) {
var iconUrl = this.getIconUrl(optValue);
domElement.style.backgroundImage = 'url(' + iconUrl + ')';
domElement.style.backgroundSize = '20px 20px';
domElement.style.backgroundRepeat = 'no-repeat';
domElement.style.backgroundPosition = 'left center';
domElement.style.paddingLeft = '30px';
}
Check out this fiddle for a working example.
This is still no good solution to me, since doing this kind of hackish DOM manipulation is way too rogue for my taste. I don't know what the side effects of actively messing around in the DOM could be in bigger projects, and don't want to learn it the hard way. So, I'm still looking for a cleaner solution.
First kudos on working so hard sencha touch is extremely hard to manipulate when you try to do something out of the box. Having said that let me try & propose a solution for what you want.
A selectfield in sencha has the following DOM tag structure.
div.x-field-select
div.x-field-input
input.x-input-el
div.x-clear-icon
div.x-field-mask
Now concentrate on the x-clear-icon it is normally hidden since a selectfield does not need a clear button. First write a css class for it to show it(display: block). This would display it with an X button similar to text field & it will be positioned towards the right corner. You can through css position it to the left and on change of the select field you can change its background to what you want. It is not a very straight forward solution but i have tried it for a similar problem & it works. Judging from what you have done above i think you can do it. All the best.
Hope my solution helps.