How to do element extraction in javascript? - javascript

I have placeholder with any web page url. It should extract the elements when i click on button. I have to show elements and xpath values in my page. How can i do that? Please help me.

I'm not sure if that is what you want, but if you need to display every element's XPath, here is my solution:
function buildDom(text) {
var div = document.createElement('div');
div.innerHTML = text;
return div.firstChild;
}
function fetchAttrs(node) { // getting attributes object for element
return node && Array.prototype.reduce.call(node.attributes, function(list, attribute) {
list[attribute.name] = attribute.value;
return list;
}, {}) || {};
};
function traverseElement(element, argPrefix = "") {
if (element.nodeType === Node.TEXT_NODE)
return; // skipping text elements
var attrs = fetchAttrs(element)
var prefix = argPrefix + "/" + element.tagName; // build element path
if (Object.keys(attrs).length !== 0){
prefix += "[" + Object.keys(attrs).map((value, index) => {
return "#" + value + ' = "' + attrs[value] + '"'
}).join(" and ") + "]" // append arguments
}
console.log(prefix);
var children = element.childNodes // iterating over children
for (var i = 0; i < children.length; i++)
{
traverseElement(children[i], prefix)
}
}
var url = "https://icanhazip.com/" // URL to load
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) { // when loaded
var dom = buildDom(this.responseText); // build a DOM tree from a response string
traverseElement(dom) // and traverse it
}
};
xhttp.open("GET", url, true);
xhttp.send(); // loading needed website

Related

How to modify anchor tags in botframework Web chat

We've just started using the bot-framework. For client side we are using the cdn and not react. We have certain links that bot responds with. And we would like to append a url parameter to each link and open the link in the same window. So far this is what my code looks like. Is there a better way to achieve this using the botframework. I know there is cardActionMiddleware which has openUrl cardAction, but we don't have any cards and I am not sure on how to implement that.
var webchatMount = document.getElementById('webchatMount');
function loadChatbot() {
var xhr = new XMLHttpRequest();
xhr.open('GET', "https://webchat.botframework.com/api/tokens", true);
xhr.setRequestHeader('Authorization', 'BotConnector ' + '<secret>');
xhr.send();
xhr.onreadystatechange = function (e) {
if (xhr.readyState == 4 && xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
var store = window.WebChat.createStore({}, function ({ dispatch }) {
return function (next) {
return function (action) {
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
var event = new Event('webchatincomingactivity');
event.data = action.payload.activity;
window.dispatchEvent(event);
}
return next(action);
}
}
});
window.WebChat.renderWebChat(
{
directLine: window.WebChat.createDirectLine({ token: response }),
store: store,
},
webchatMount
);
document.querySelector('.webchat__send-box-text-box__input').focus();
window.addEventListener('webchatincomingactivity', ({ data }) => {
setTimeout(function () {
var links = document.querySelectorAll('#webchatMount a');
if (links.length >= 1) {
for (var i = 0; i <= links.length; i++) {
if (links[i] == undefined)
break;
var compare = new RegExp('maindomain');
var href = links[i].getAttribute('href');
var st = getParameterByName('st', href);
if (links[i].hasAttribute('target')) {
links[i].removeAttribute('target');
}
if (compare.test(href)) {
// internal link
// check if it has st=INTRA
if (st) {
console.log(' it has a value');
} else {
links[i].setAttribute('href', insertParam('st', 'INTRA', href));
}
} else {
// external link, do nothing
}
}
}
}, 1000);
});
}
}
}
and here are getParameterByName and insertParam functions.
function getParameterByName(name, url) {
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
function insertParam(key, value, url) {
key = encodeURIComponent(key);
value = encodeURIComponent(value);
// kvp looks like ['key1=value1', 'key2=value2', ...]
var kvp = url.split('&');
var i=0;
for(; i<kvp.length; i++){
if (kvp[i].startsWith(key + '=')) {
var pair = kvp[i].split('=');
pair[1] = value;
kvp[i] = pair.join('=');
break;
}
}
if(i >= kvp.length){
kvp[kvp.length] = [key,value].join('=');
}
return kvp.join('&');
}
I am new to botframework webchat so I don't know it very well. I know that the secret should not be used like that, but for know we are testing and would like to get it to work. Any help would be appericiated
Thanks.

mediawiki api can not display the results from array

Hello you wonderful people, I am trying to build JavaScript file to extract information from Wikipedia based on search value in the input field and then display the results with the title like link so the user can click the link and read about it. So far I am getting the requested information in(JSON)format from Mediawiki(Wikipedia) but I can't get it to display on the page. I think I have an error code after the JavaScript array.
I'm new at JavaScript any help, or hint will be appreciated.
Sorry my script is messy but I am experimenting a lot with it.
Thanks.
var httpRequest = false ;
var wikiReport;
function getRequestObject() {
try {
httpRequest = new XMLHttpRequest();
} catch (requestError) {
return false;
}
return httpRequest;
}
function getWiki(evt) {
if (evt.preventDefault) {
evt.preventDefault();
} else {
evt.returnValue = false;
}
var search = document.getElementsByTagName("input")[0].value;//("search").value;
if (!httpRequest) {
httpRequest = getRequestObject();
}
httpRequest.abort();
httpRequest.open("GET", "https://en.wikipedia.org/w/api.php?action=query&format=json&gsrlimit=3&generator=search&origin=*&gsrsearch=" + search , true);//("get", "StockCheck.php?t=" + entry, true);
//httpRequest.send();
httpRequest.send();
httpRequest.onreadystatechange = displayData;
}
function displayData() {
if(httpRequest.readyState === 4 && httpRequest.status === 200) {
wikiReport = JSON.parse(httpRequest.responseText);//for sunchronus request
//wikiReport = httpRequest.responseText;//for asynchronus request and response
//var wikiReport = httpRequest.responseXML;//processing XML data
var info = wikiReport.query;
var articleWiki = document.getElementsByTagName("article")[0];//creating the div array for displaying the results
var articleW = document.getElementById("results")[0];
for(var i = 0; i < info.length; i++)
{
var testDiv = document.createElement("results");
testDiv.append("<p><a href='https://en.wikipedia.org/?curid=" + query.pages[i].pageid + "' target='_blank'>" + query.info[i].title + "</a></p>");
testDiv.appendChild("<p><a href='https://en.wikipedia.org/?curid=" + query.info[i].pageid + "' target='_blank'>" + query.info[i].title + "</a></p>");
var newDiv = document.createElement("div");
var head = document.createDocumentFragment();
var newP1 = document.createElement("p");
var newP2 = document.createElement("p");
var newA = document.createElement("a");
head.appendChild(newP1);
newA.innerHTML = info[i].pages;
newA.setAttribute("href", info[i].pages);
newP1.appendChild(newA);
newP1.className = "head";
newP2.innerHTML = info[i].title;
newP2.className = "url";
newDiv.appendChild(head);
newDiv.appendChild(newP2);
articleWiki.appendChild(newDiv);
}
}
}
//
function createEventListener(){
var form = document.getElementsByTagName("form")[0];
if (form.addEventListener) {
form.addEventListener("submit", getWiki, false);
} else if (form.attachEvent) {
form.attachEvent("onsubmit", getWiki);
}
}
//createEventListener when the page load
if (window.addEventListener) {
window.addEventListener("load", createEventListener, false);
} else if (window.attachEvent) {
window.attachEvent("onload", createEventListener);
}
Mediawiki api link
https://en.wikipedia.org/w/api.php?action=query&format=json&gsrlimit=3&generator=search&origin=*&gsrsearch=
You are wrong some points.
1)
var articleW = document.getElementById("results")[0];
This is wrong. This will return a element is a reference to an Element object, or null if an element with the specified ID is not in the document. Doc is here (https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById)
The correct answer should be :
var articleW = document.getElementById("results");
2)
var info = wikiReport.query;
for(var i = 0; i < info.length; i++) {}
The info is object . it is not array , you can't for-loop to get child value.
wikiReport.query is not correct wiki data. The correct data should be wikiReport.query.pages. And use for-in-loop to get child element
The correct answer:
var pages = wikiReport.query.pages
for(var key in pages) {
var el = pages[key];
}
3) This is incorrect too
testDiv.appendChild("<p><a href='https://en.wikipedia.org/?curid=" + query.info[i].pageid + "' target='_blank'>" + query.info[i].title + "</a></p>");
The Node.appendChild() method adds a node to the end of the list of children of a specified parent node. You are using the method to adds a string . This will cause error. Change it to node element or use append method instead
I have created a sample test.You can check it at this link below https://codepen.io/anon/pen/XRjOQQ?editors=1011

How can I show with PhantomJS the url of the processed page in the generated PDF?

My goal was to generate a PDF from every page included in the sitemap of a website created with Rails. I'm using PhantomJS to get it. I'm quite new in this field, but I could do it, but when I was finished, I realized that it would be usable also to see at the beginning of every PDF the url of the page from which the PDF was generated, so I can browse quicker to the page (the site has over hundred pages).
Here is the Javascript:
// Render Sitemap to file
var RenderUrlsToFile, arrayOfUrls, system;
system = require("system");
/*
Render given urls
#param array of URLs to render
#param callbackPerUrl Function called after finishing each URL, including the last URL
#param callbackFinal Function called after finishing everything
*/
var getFileNumber = function(urlIndex) {
if (urlIndex <10) {
return "00" + urlIndex;
} else {
if (urlIndex <100) {
return "0" + urlIndex;
} else {
return urlIndex;
}
}
};
RenderUrlsToFile = function(urls, callbackPerUrl, callbackFinal) {
var getFilename, next, page, retrieve, urlIndex, webpage;
urlIndex = 0;
webpage = require("webpage");
page = null;
getFilename = function() {
return "rendermulti-" + getFileNumber(urlIndex) + ".pdf";
};
next = function(status, url, file) {
page.close();
callbackPerUrl(status, url, file);
return retrieve();
};
retrieve = function() {
var url;
if (urls.length > 0) {
url = urls.shift();
urlIndex++;
page = webpage.create();
page.viewportSize = {
width: 1920,
height: 1880
};
page.settings.userAgent = "Phantom.js bot";
return page.open(url, function(status) {
var file;
file = getFilename();
if (status === "success") {
return window.setTimeout((function() {
// !!!!!!!!!!!!! Doesn't work !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
page.evaluate(function() {
var x = document.getElementById("logoAndNavigation");
var newP = document.createElement("P")
var textnode = window.location.protocol + "//" + window.location.host + "/" + window.location.pathname;
newP.appendChild(textnode)
x.insertBefore(newP, x.childNodes[0]);
});
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
page.render("tempPdfs/" + file);
return next(status, url, file);
}), 200);
} else {
return next(status, url, file);
}
});
} else {
return callbackFinal();
}
};
return retrieve();
};
// This makes an array with all the urls inside the sitemap
var arrayOfUrls = [''];
var page = require('webpage').create();
page.open('http://localhost:3000/sitemap.xml', function() {
var content = page.content;
parser = new DOMParser();
xmlDoc = parser.parseFromString(content,'text/xml');
var loc = xmlDoc.getElementsByTagName('loc');
for(var i=0; i < loc.length; i++)
{
var url=loc[i].textContent;
arrayOfUrls.push(url);
}
});
RenderUrlsToFile(arrayOfUrls, (function(status, url, file) {
if (status !== "success") {
return console.log("Unable to render '" + url + "'");
} else {
return console.log("Rendered '" + url + "' at '" + file + "'");
}
}), function() {
return phantom.exit();
});
I tried to solve the issue with the urls, with the code framed with the comment
// !!!!!!!!!!!!! Doesn't work !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
I wanted to show the url inside an element of the page, that has the id #logoAndNavigation, but I get this error:
NOT_FOUND_ERR: DOM Exception 8: An attempt was made to reference a Node in a context where it does not exist.
If I use only a string like "hello" inside the variable textnode, it works, but not if I try to use the url of the page.
Can anyone please help me?
Thank you in advance!
appendChild expects a node not a string. You probably mean to use
var x = document.getElementById("logoAndNavigation");
var newP = document.createElement("p"); // small p
var textnode = window.location.protocol + "//" + window.location.host + "/" + window.location.pathname;
newP.innerHTML = textnode; // this
x.insertBefore(newP, x.childNodes[0]);
You can also use the example of printheaderfooter.js to add the URL directly to the header or footer.

Intermittent behavior in my AJAX, Greasemonkey script

I've a small Greasemonkey script that doesn't include any random part, but its results change with each page reload.
I'm a noob and I'm probably doing something wrong, but I don't know what. I hope you'll be able to help me.
The code is too large and too poorly written to be reproduced here, so I'll try to sum up my situation:
I have a list of links which have href=javascript:void(0) and onclick=f(link_id).
f(x) makes an XML HTTP request to the server, and returns the link address.
My script is meant to precompute f(x) and change the href value when the page loads.
I have a function wait() that waits for the page to load, then a function findLinks() that gets the nodes that are to be changed (with xpath).
Then a function sendRequest() that sends the xhr to the server. And, finally handleRequest() that asynchronously (r.onreadystatechange) retrieves the response, and sets the nodes previously found.
Do you see anything wrong with this idea?
Using a network analyzer, I can see that the request is always sent fine, and the response also.
Sometimes the href value is changed, but sometimes for some links it isn't and remains javascript:void(0).
I really don't see why it works only half the time...
function getUrlParameterFromString(urlString, name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(urlString);
if (results == null) {
return "";
} else {
return results[1];
}
}
function getUrlParameter(name) {
return getUrlParameterFromString(window.location.href, name);
}
function wait() {
var findPattern = "//a";
var resultLinks = document.evaluate(findPattern, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (resultLinks == null || resultLinks.snapshotLength == 0) {
return setTimeout(_wait, 100);
} else {
for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
var node = resultLinks.snapshotItem(i);
var s = node.getAttribute('onclick');
var linkId = s.substring(2, s.length - 1); // f(x)->x
sendRequest(linkId, node);
}
}
}
function sendRequest(linkId, nodeToModify) {
window.XMLHttpRequest ? r = new XMLHttpRequest : window.ActiveXObject && (r = new ActiveXObject("Microsoft.XMLHTTP"));
if (r) {
r.open("POST", "some_url", !0);
r.onreadystatechange = function () {
handleRequest(nodeToModify, linkId, r);
}
r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
r.send(linkId);
}
}
function handleRequest(nodeToModify, num, r) {
if (r.readyState == 4) {
if (r.status == 200) {
console.log('handleRequest() used');
var a = r.responseText;
if (a == null || a.length < 10) {
sendRequest(num, nodeToModify);
} else {
var url = unescape((getUrlParameterFromString(a, "url")).replace(/\+/g, " "));
nodeToModify.setAttribute('href', url);
nodeToModify.setAttribute('onclick', "");
}
} else {
alert("An error occurred: " + r.statusText)
}
}
}
wait();
It looks like that script will change exactly 1 link. Look-up "closures"; this loop:
for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
var node = resultLinks.snapshotItem(i);
var s = node.getAttribute('onclick');
var linkId = s.substring(2, s.length - 1); // f(x)->x
sendRequest(linkId, node);
}
needs a closure so that sendRequest() gets the correct values. Otherwise, only the last link will be modified.
Try:
for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
var node = resultLinks.snapshotItem(i);
var s = node.getAttribute('onclick');
var linkId = s.substring(2, s.length - 1); // f(x)->x
//-- Create a closure so that sendRequest gets the correct values.
( function (linkId, node) {
sendRequest (linkId, node);
}
)(linkId, node);
}

Parsing the url querystring using jquery and inserting the value in a textbox?

post.php?replyto=username&othervariable=value
For example, if I click a link with this url, then I want to take the replyto=username value and insert the value in a textbox using jquery.
function insertParamIntoField(url, param, field) {
var anchor = document.createElement('a'), query;
anchor.value = url;
query = anchor.query.split('&');
for(var i = 0, kv; i < query.length; i++) {
kv = query[i].split('=', 2);
if (kv[0] == param) {
field.value = kv[1];
return;
}
}
}
$("a .reply").click(function () {
insertParamIntoField(this.href, "replyto", $("input .inputField")[0]);
return false; // prevent default action
});
this is my html code:
<textarea name="inputField" id="inputField" tabindex="1" rows="2" cols="40"></textarea>
<a class ="reply" href="home.php?replyto=username">reply</a>
function insertParamIntoField(url, param, field) {
var anchor = document.createElement('a'), query;
anchor.href = url;
query = anchor.search.substring(1, anchor.search.length).split('&');
for(var i = 0, kv; i < query.length; i++) {
kv = query[i].split('=', 2); console.log(kv);
if (kv[0] == param) {
field.value = kv[1];
return;
}
}
}
$("a.reply").click(function () {
insertParamIntoField(this.href, "replyto", $("textarea.inputField")[0]);
return false; // prevent default action
});
The insertParamIntoField function will work for any well formed URL (as a string). It works by creating a new anchor DOMElement (but never attaches it to the dom) for that URL and then by using the built in properties of anchor elements (query, hash, etc.) to extract what we want.
If the URL is from an anchor element, we can create a new version of this function that uses that existing anchor rather than creating a new one:
function insertParamIntoField(anchor, param, field) {
var query = anchor.search.substring(1, anchor.search.length).split('&'); // anchor is a DOMElement
for(var i = 0, kv; i < query.length; i++) {
kv = query[i].split('=', 2);
if (kv[0] == param) {
field.value = kv[1];
return;
}
}
}
$("a.reply").click(function () {
insertParamIntoField(this, "replyto", $("textarea.inputField")[0]);
return false; // prevent default action
});
Parsing the URL can be done with a simple function. Use this in your Javascript:
$.urlParam = function(name){
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
return results[1] || 0;
}
You can then call:
$.urlParam('username');
and it will return the user name. So, to actually use it with your text box, do:
$('#textBoxId').val($.urlParam('username'));
$('textarea').val("<?php echo $_GET['replyto']");
Using the code from this SO answer (which is great btw) by Artem Barger to get any parameter by name from the query string you could do:
function getParameterByName( name )
{
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if(results == null )
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
Then just insert the value into the textbox:
$("#yourTextBox").val(getParameterByName('replyto'));
You should be able to grab the ?replyto=username&othervariable=value part with window.location.search, then you have to get the part you want
var print = '?replyto=username&othervariable=value'; // Would be window.location.search in practice
$('textBox').val(print.substr(print.indexOf('replyto=')+8,print.indexOf('&')-(print.indexOf('replyto=')+8)));
​
Here is some Javascript that should help you. Just take the return value from the getQuerystringNameValue() function and use $("#textboxID").val(returnValue); to assign it to the textbox.
alert("name1" + " = " + getQuerystringNameValue("name1"));
alert("name2" + " = " + getQuerystringNameValue("name2"));
alert("name3" + " = " + getQuerystringNameValue("name3"));
function getQuerystringNameValue(name)
{
// For example... passing a name parameter of "name1" will return a value of "100", etc.
// page.htm?name1=100&name2=101&name3=102
var winURL = window.location.href;
var queryStringArray = winURL.split("?");
var queryStringParamArray = queryStringArray[1].split("&");
var nameValue = null;
for ( var i=0; i<queryStringParamArray.length; i++ )
{
queryStringNameValueArray = queryStringParamArray[i].split("=");
if ( name == queryStringNameValueArray[0] )
{
nameValue = queryStringNameValueArray[1];
}
}
return nameValue;
}

Categories

Resources