Iam stuck with the code. The javascript variable Retimgexp is returning as "", Not sure why. It only returns "undefined" when I click on the body of the page.
Basically what I am trying to achieve is when user clicks on image i wanted to grab the href of the parent "a" element and push it ultimately to the GA TAG using variables, so i have made modifications to the code.
can you please have a look.
Custom javascript File name:- Find closest
function() {
return function(target, selector) {
while (!target.matches(selector) && !target.matches('body')) {
target = target.parentElement;
}
return target.matches(selector) ? target : undefined;
}
}
Custom javascript File name:- Retimgexp
function() {
var el = {{Find closest}}({{Click Element}}, 'a[href^="http"]');
return typeof el !== 'undefined' ? el.id : undefined;
}
Basically this is the HTML code
<div class="card__media-overlapping__media">
<a href="https://capgemini.aws.hmn.md/experts/it-strategy-and-transformation/yvette-zzauer/">
<img src="https://eu-west-1.tchyn.io/capgemini-dev/uploads/2017/07/yvette_zzauer.jpg?resize=324,197" alt="Yvette Zzauer">
</a>
</div>
Its Working now
I was referencing the ID which was wrong should have referenced "href". Its working now.
function() {
var el = {{Find closest}}({{Click Element}}, 'a[href^="http"]');
return typeof el !== 'undefined' ? el.href : undefined;
}
Oki one of the simplest way could be a one liner, then you can check for the fallback condition etc
{{Click Element}}.parentNode.getAttribute("href");
Related
I'm trying to make a bot that scrapes links from a website. I am running in to some weird error that I cannot figure out. My guess is that the second if statement is failing to check and also my unfamiliarity with jQuery is not helping.
Error:
element.each is not a function
const $ = load(html);
const html = $("#id");
const temp = [];
function recursive(element) {
if (element.name === "a") {
temp.push(element);
}
if (!element || element.children().length > 0 === false) {
return "DID NOT FIND IT OR NO CHILDREN FOUND";
}
return element.each((_, item) => recursive(item));
}
recursive(html);
return temp;
I've tried to create simple snippet demonstrating what you seem to accomplished with JQuery.
Firstly, your check if for the Tag of an element doesn't seemed to be working properly. I had to use the .prop('tagName') to get the Tag of the element. And it gets returned in all capital letters.
Your second IF-Statement should work fine, but the .each() Method didnt work as expected. You want to iterate through all children and start the recursive function. And the way you provided the child element didnt end up working.
The .each() Method want a callback function which provides two parameters as you have uses correctly. but the Item is a normal HTML Node and you had to select it with the JQuery Constant $ like $(item). This gives you the desired JQuery Element you can work with.
const html = $("#test");
const temp = [];
function recursive(element) {
if (element.prop("tagName") === "A") {
temp.push(element);
}
if (!element || element.children().length > 0 === false) {
return "DID NOT FIND IT OR NO CHILDREN FOUND";
}
return element.children().each((i, item) => recursive($(item)));
}
recursive(html);
console.log(temp)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="test">
<div class="headings">
<h1>Heading</h1>
Main Page
</div>
<div class="test-cls">
<button>Hello</button>
Test Page
</div>
</div>
Suppose I have the following structure:
<html>
<head></head>
<body>
<div id="myDiv"></div>
</body>
</html>
By redefining some native JavaScript functions, can I make myDiv unfindable?
For example, I can do:
window.HTMLDocument.prototype.getElementById = (function() {
var oldefinition = window.HTMLDocument.prototype.getElementById;
return function() {
var returnValue = oldefinition.apply(this, arguments);
if (returnValue && returnValue.id === 'myDiv') {
return oldefinition.call(this, 'blablabla');
} else {
return returnValue;
}
}
})();
and I can do the same for the other functions such as:
querySelector
querySelectorAll
getElementsByTagName
getElementsByClassName
etc.
This works, but the div is still available by calling:
document.body.children[0]
Then is there a way to make my div unfindable, that is, can I redefine the value of the children field?
Well, this is an attempt that seems to work okay - at least, with regards to document.body.children. I tested a variation of the following code on MDN's website to hide all script tags that are immediate children of the document body.
The way this works is we tell document.body to use a new property called children. We then return the original contents of children, minus the ones we don't want.
var oldchildren = document.body.children;
Object.defineProperty(document.body, 'children', {
get() {
var lst = [];
for (var item of oldchildren) {
if (!(item.tagName === "div" && item.id === 'myDiv'))
lst.push(item);
}
return lst;
}
});
Any code that references document.body.children after this code runs won't see the div. This code might cause other code on your site to misbehave.
I have a simple function that traverses up the DOM to get to a span element:
function getAttachmentControlBinding(theNode) {
//Find the <SPAN> tag that has the binding to the attachment control
//The attachment control is needed to be able to determine from which view
do {
//Navigate up to the parent node
theNode = theNode.parentNode;
//Should run into a <SPAN> tag, but if not we need to get out of the loop
} while (theNode.nodeName !== "SPAN" && theNode.nodeName !== '');
//Get the value of the binding attribute from the <SPAN> tag
return theNode.getAttribute("binding");
}
In the JS console, if I look at theNode, I get this:
<span id="svattachmentcontainer_0_1" binding="my:wsAttachmentCreditApplication"
The binding here is what I want the function to return; however I keeping getting an error of illegal return statement if I try to evaluate in the console. If I evaluate theNode.getAttribute("binding") in the console, I get what I want (my:wsAttachmentCreditApplication), but letting the code run jumps to a completely different section of code that would normally run if this function return was successful.
How can I return this value with this function?
Your code works fine
function getAttachmentControlBinding(theNode) {
//Find the <SPAN> tag that has the binding to the attachment control
//The attachment control is needed to be able to determine from which view
do {
//Navigate up to the parent node
theNode = theNode.parentNode;
//Should run into a <SPAN> tag, but if not we need to get out of the loop
} while (theNode.nodeName !== "SPAN" && theNode.nodeName !== '');
//Get the value of the binding attribute from the <SPAN> tag
return theNode.getAttribute("binding");
}
var binding = getAttachmentControlBinding(document.querySelector('.nesteddiv2'));
document.querySelector('.js-result').innerHTML = 'Binding found: ' + binding;
<span id="svattachmentcontainer_0_1" binding="my:wsAttachmentCreditApplication">
<div class="nesteddiv1">
<div class="nesteddiv2"></div>
</div>
</span>
<div class="js-result">aa</div>
I need to put span tags around first word in a line. I used the below Jquery which is working fine in sitecore standard mode.
$("body").has(".widget h2").addClass("standard-mode");
$("body").has(".scLoadingIndicatorInner").removeClass("standard-mode").addClass("page-edit");
$('.standard-mode .widget h2').html(function(i, html){
return html.replace(/(\w+\s)/, '<span>$1</span>')
})
When i first load the page editor this works fine as well(by not inserting the span tags), but when i created a multivariate test switching between the A/B by using arrow marks shows like inserting the span tags which it should not suppose to do as it is in page-edit mode but it does and breaking the html as below.
<h2>
<<span>input </span>id="fld_D26C954B73BE4C62B6F25BE191A86F18_7B55B5E5EDD84D4E88B16C6E073495A5_en_1_0e80a9c63ab6419f8135b70511e892f1_16487" class="scFieldValue" name="fld_D26C954B73BE4C62B6F25BE191A86F18_7B55B5E5EDD84D4E88B16C6E073495A5_en_1_0e80a9c63ab6419f8135b70511e892f1_16487" type="hidden" value="Badger Cull"><span class="scChromeData">{"commands":[{"click":"chrome:common:edititem({command:\"webedit:open\"})","header":"Edit the related item","icon":"/temp/IconCache/SoftwareV2/16x16/cubes_blue.png","disabledIcon":"/temp/cubes_blue_disabled16x16.png","isDivider":false,"tooltip":"Edit this item in the Content Editor.","type":"common"},{"click":"chrome:rendering:personalize({command:\"webedit:personalize\"})","header":"Personalize","icon":"/temp/IconCache/PeopleV2/16x16/users3_edit.png","disabledIcon":"/temp/users3_edit_disabled16x16.png","isDivider":false,"tooltip":"Personalize component.","type":"sticky"},{"click":"javascript:Sitecore.PageModes.PageEditor.postRequest('ActiveISPageEditor:publish(id={D26C954B-73BE-4C62-B6F2-5BE191A86F18})',null,false)","header":"Publish the related item","icon":"/temp/IconCache/Network/16x16/download.png","disabledIcon":"/temp/download_disabled16x16.png","isDivider":false,"tooltip":"Publish this item.","type":"common"},{"click":"chrome:rendering:editvariations({command:\"webedit:editvariations\"})","header":"Edit variations","icon":"/temp/IconCache/SoftwareV2/16x16/breakpoints.png","disabledIcon":"/temp/breakpoints_disabled16x16.png","isDivider":false,"tooltip":"Edit the variations.","type":"sticky"}],"contextItemUri":"sitecore://master/{D26C954B-73BE-4C62-B6F2-5BE191A86F18}?lang=en&ver=1","custom":{},"displayName":"Header Text","expandedDisplayName":null}</span><span scfieldtype="single-line text" sc_parameters="prevent-line-break=true" contenteditable="false" class="scWebEditInput scEnabledChrome" id="fld_D26C954B73BE4C62B6F25BE191A86F18_7B55B5E5EDD84D4E88B16C6E073495A5_en_1_0e80a9c63ab6419f8135b70511e892f1_16487_edit" sc-part-of="field">Badger Cull</span>
</h2>
Any suggestions will be helpful.
You can check the JavaScript property Sitecore.PageModes.PageEditor to see if you are in page editor mode and can disable your javascript accordingly.
function isPageEditor() {
if (typeof Sitecore == "undefined") {
return false;
}
if (typeof Sitecore.PageModes == "undefined" || Sitecore.PageModes == null) {
return false;
}
return Sitecore.PageModes.PageEditor != null;
}
if (isPageEditor() == false) {
//do your stuff here
}
<a href="javascript:void(0)" class="PrmryBtnMed"
id = "VERYLONGTEXT"
onclick="$(this).parents('form').submit(); return false;"><span>Dispatch to this address</span></a>
If I was to give instructions to a human, I would say:
look for a <span>Dispatch to this address</span> link; if it appears click it. (if there is more than one such link (for example there are two) just click the first one (or any of them)
I am using Greasekit, so I am looking to do this using JavaScript.
Thank you!
Updated: Now checks contents of element
var el = document.querySelector(".PrmryBtnMed"); //should only return first one
if (el && (el.textContent.trim() == 'Dispatch to this address')) {
el.click();
}
Have a look at the querySelector and textContent for more information
I also added a JsFiddle for you: http://jsfiddle.net/NrGVq/1/
A different approach is to search the whole page, in case it's not inside the matched element
var inPage = document.documentElement.innerHTML.indexOf('text to search') > 0,
el = document.querySelector(".PrmryBtnMed");
if (inPage && el) el.click();