I'm developing a Chrome Extension where I need to retrieve the source code of a newly create tab.
Retrieving the source code is not a problem as such, my script below does that perfectly but what I'm looking for is to get the source code once the page has been completely loaded included dynamic content that has been inserted after page load (like with Ajax for example).
To get the source code, I'm using
chrome.tabs.executeScript(tabId,
{
file: 'test.js',
}, function(results)
{
// DO SOMETHING HERE
}
test.js contains the following:
function DOMtoString(document_root) {
var html = '',
node = document_root.firstChild;
while (node) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
html += node.outerHTML;
break;
case Node.TEXT_NODE:
html += node.nodeValue;
break;
case Node.CDATA_SECTION_NODE:
html += '<![CDATA[' + node.nodeValue + ']]>';
break;
case Node.COMMENT_NODE:
html += '<!--' + node.nodeValue + '-->';
break;
case Node.DOCUMENT_TYPE_NODE:
// (X)HTML documents are identified by public identifiers
html += "<!DOCTYPE " + node.name + (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '') + (!node.publicId && node.systemId ? ' SYSTEM' : '') + (node.systemId ? ' "' + node.systemId + '"' : '') + '>\n';
break;
}
node = node.nextSibling;
}
return html;
}
chrome.runtime.sendMessage({
action: "getSource",
source: DOMtoString(document),
metadata: shop_metadata
});
What I would like to do is to retrieve the source code only when a class has been detected and if it failed after a couple of seconds, the script should skip the process. The class I'm looking for is available in the "shop_metadata" variable.
Is there a way to make that happen with SendMessage like in my script?
I have tried to do this:
function test (document)
{
var checkExist = setInterval(function()
{
if ($('.product-title').length)
{
console.log("Exists!");
source = DOMtoString(document);
console.log(source);
return source;
clearInterval(checkExist);
}
}, 5000);
}
and then modify my message:
chrome.runtime.sendMessage({
action: "getSource",
source:test(document),
metadata: shop_metadata
});
If I executed this in the console, I get the source code with the dynamic content but when I checked the content of "source" in the extension, it returns "undefined"
Thanks
Laurent
Related
I have this code installed on my website and what it is suppose to do is see if a product has a single or double attribute and then it disables products from there that are out of stock so customers can't click on it. The code works great for the single attribute products but it doesn't seem to work for the double attribute products.
Single Attribute Product link - https://true-grit-running-company.shoplightspeed.com/goodr-sunglasses.html
Double Attribute Product link - https://true-grit-running-company.shoplightspeed.com/womens-bondi-7.html?id=65554420&quantity=1
`
// A quick check to see if it is a product being viewed (checking the microdata) - to avoid running the rest of the code if viewing a page other than the product page
if ($('[itemtype*="//schema.org/Product"]').length > 0) {
//Check the url to see if a variant is being viewed or not
var curl = location.href;
//choose the appropriate ajax url
if (curl.indexOf('?') > -1) {
var url = curl + '&format=json';
} else {
var url = '?format=json';
}
//Start the ajax call
$.ajax({
url: url,
})
// Add the disabled attribute to the variants that aren't available
.done(function(obj) {
//create a variable with the product variants
var data = obj.product.variants;
//fun a function on each variant
$.each(data, function(index, value) {
//check if any of the variants aren't available for purchase
if (!value.stock.available) {
//CODE FOR DOUBLE ATTRIBUTE VARIANTS
//check if the variants are double attribute
if (value.title.indexOf(',') > -1) {
console.log('Double Attribute matrix!');
var attribute1 = value.title.replace(/"/g,'').split(',')[0].split(": ")[1];
//only disable the variants for which the first attribute is being viewed
if ($('select[name*="matrix"]:first()').val() == attribute1) {
var option = value.title.replace(/"/g,'').split(',')[1].split(":")[1];
$('select[name*="matrix"] option:contains(' + option + ')').each(function(){
if ($(this).text() == option) {
$(this).attr('disabled', 'true');
}
});
}
//CODE FOR SINGLE ATTRIBUTE VARIANTS
} else {
console.log('Single Attribute matrix!');
var option = value.title.split(': ')[1];
var selectname = value.title.split(': ')[0];
$('select[name*="matrix"] option:contains(' + option + ')').each(function(){
if ($(this).text() == option) {
$(this).attr('disabled', 'true');
}
});
}
}
})
});
} else {
console.log('not a product page!');
}
`
I have a document library on SharePoint online with lots of columns for metadata. These columns won't fit in a single view on screen, so I want the users to first view the properties of the file before downloading them.
Is there a way to change the behavior of the SharePoint library ensure that the user views the file properties first when they click on the filename?
PS: I understand I could have used lists, but after loading about 10000 documents, I have decided to use it as a last resort. Thank you.
Custom the LinkFilename field by CSR.
Sample code:
(function () {
'use strict';
var CustomWidthCtx = {};
/**
* Initialization
*/
function init() {
CustomWidthCtx.Templates = {};
CustomWidthCtx.Templates.Fields = {
'LinkFilename': {
'View': customDisplay
}
};
// Register the custom template
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(CustomWidthCtx);
}
/**
* Rendering template
*/
function customDisplay(ctx) {
var currentVal = '';
//from the context get the current item and it's value
if (ctx != null && ctx.CurrentItem != null)
currentVal = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
var el = "<div class='ms-vb itx' id='" + ctx.CurrentItem.ID + "' app='' ctxname='ctx37'><a title='" + ctx.CurrentItem._ShortcutUrl + "' class='ms-listlink ms-draggable' aria-label='Shortcut file' onfocus='OnLink(this)' href='/Doc4/Forms/EditForm.aspx?ID=" + ctx.CurrentItem.ID + "' target='_blank' DragId='17'>" + ctx.CurrentItem.FileLeafRef + "</a></div>";
// Render the HTML5 file input in place of the OOTB
return el;
}
// Run our intiialization
init();
})();
I am trying to modify an existing chrome extention.
What i want is a chrome extention where i populate a popup window full of urls and then when i click OK each url opens up in a new tab 1 at a time, certain data on that tab is then copied somewhere, the tab closes and the next url in the list is called and so on untill the list is complete. the extention finally outputs all the copied data from all the tabs into a CSV file (which i can then manipulate into Excel.
I have looked everywhere but so far i have only got as far as to open the tabs up HOWEVER they all open at the same time. this i sas far as i have got.
I have tried using chrome.tabs.execute script and that seems to block the loop,
Any ideas?
EDIT - HERE IS THE FULL CODE
Many Thanks
function loadSites(e) {
var urlschemes = ['http', 'https', 'file', 'view-source'];
var urls = document.getElementById('urls')
.value.split('\n');
var lazyloading = document.getElementsByName('lazyloading')[0].checked;
for (var i = 0; i < urls.length; i++) {
theurl = urls[i].trim();
if (theurl != '') {
if (urlschemes.indexOf(theurl.split(':')[0]) == -1) {
theurl = 'http://' + theurl;
}
if (lazyloading && theurl.split(':')[0] != 'view-source' && theurl.split(':')[0] != 'file') {
chrome.tabs.create({
url: chrome.extension.getURL('lazyloading.html#') + theurl,
selected: false
});
} else {
chrome.tabs.create({
url: theurl,
selected: true,
activ
function(tab) {
chrome.tabs.executeScript(tab.id, { file: "contentscript.js" });
});
}
}
}
}
I use MongoDBClient in Node.js, and Pug.
I would want to get all my pizzerias' name in my database. Thus, I wrote this line : collection.find({cook:'Pizza'}) to select all the pizzerias, and the attribute "name" exists.
But find returns a cursor, thus I can't directly use its return like that : var array_pizzerias_names = collection.find({cook:'Pizza'}).get('name'). (NB : I know the funciton get doesn't exist).
How could I do it ?
In my Pug file, I wrote these few lines :
- for(var i = 0; i < array_pizzerias_names.length; i++) {
p=array_pizzerias_names[i].name
- }
I found a solution.
MongoClient (require('mongodb').MongoClient) provides a find method signature which takes 2 parameters, and the second is a callback ; the last parameter of the latter is a cursor which have a method toArray.
The method toArray takes a callback ; its last parameter is the array containing all the results of the find, and can be used in Pug.
The below code works.
Node.js code (JavaScript file) :
collection.find({cuisine: speciality}, (error, cursor) => {
handleError(error, res);
cursor.toArray((error, array_results) => {
handleError(error, res);
app.locals.speciality = speciality;
app.locals.array_documents = array_results;
res.render("speciality.pug");
});
});
Pug file :
doctype html
html(lang='fr')
head
title='Speciality'
body
h1 Speciality : #{speciality} - Number of buildings : #{array_documents.length}
- for(var i = 0; i < array_documents.length; i++) {
p=array_documents[i].name + " - Address : " + array_documents[i].address.street + " " + array_documents[i].borough + ", building n°" + array_documents[i].address.building
- }
I have a WSDL which has multiple operations. For each op i want a template .xml with its response and request.
I know how to do this manually in soapUI but I would like to generate them using a groovy script.
I googled a lot already, but seems I'm the only one who is looking for this.
My service has 16 Operations, so to do this manual would be too much time. Since the service gets updates every 2 months, an automation using a test step would be perfect.
I managed to do it for the requests already:
right-click on ´services´ in left tree, ´Generate Test Suite´, ´Single Test Case with one Request for each Operation´
then I loop through those Test Step Requests and store them on my disk.
import com.eviware.soapui.impl.wsdl.teststeps.*
for( testCase in testRunner.testCase.testSuite.getTestCaseList() )
{
for( testStep in testCase.getTestStepList() )
{
if( testStep instanceof WsdlTestRequestStep )
{
log.info "operation name: " +testStep.getName()
// create file name
Date startTime = new Date();
def cur_Time = startTime.getMonth() + "_" + startTime.getDate();
cur_Time = cur_Time + "_" + startTime.getHours() + startTime.getMinutes() +startTime.getSeconds()
def fileName = testStep.getName() + "_" + cur_Time
def inputFileRequest = new File("T:\\"+ "Request_" + fileName+".txt")
def inputFileResponse = new File("T:\\"+ "Response_" + fileName+".txt")
// write request to file
inputFileRequest.write(testStep.getProperty("request").value)
}
}
}
But I havent figured out a way to do this also for the resposes.
If i use getProperty("reponse") it's null of course.
Any hint? :)
and the winner is, I figured it out myself:
map = context.testCase.testSuite.project.interfaces["services"].operations
for (entry in map)
{
opName = entry.getKey()
inputFileRequest = new File("T:\\" + opName + "Request.xml")
inputFileResponse = new File("T:\\" + opName + "Response.xml")
inputFileRequest.write(entry.getValue().createRequest(true))
inputFileResponse.write(entry.getValue().createResponse(true))
}
This is great , even I am also working on the same. As of now I am taking xml request from a folder but I just want to get the Request from WSDL itself and want to get it's parameter.
try{
//Hitting the WSDLs one by one
wsdlList.each
{
wsdl ->
wsdlToHit=wsdl
log.info("WSDL To Hit :" + wsdlToHit)
// Creating an interface
log.info("Before Interface Creation")
iface= WsdlInterfaceFactory.importWsdl( project,wsdl, false )[0]
//iface= WsdlInterfaceFactory.importWsdl( project,WSDLFile, false )[0]
log.info("After Interface Creation")
if(Operation == "xyz")
{
requestXML= requestXML1
responseActual= responseActual1
expectedActual=expectedActual1
}
if(Operation == "abc")
{
requestXML= requestXML2
responseActual= responseActual2
expectedActual=expectedActual2
}
requestXML.each
{
request1 ->
def wsdlReqDir=request1
log.info("RequestLocation : " + wsdlReqDir)
File fl = new File(wsdlReqDir)
File[] wsdlDirFiles = fl.listFiles()
log.info("XML Files in Request Folder : " + wsdlDirFiles)
if(wsdlDirFiles.size()>0)
{
wsdlDirFiles.each
{
wsdlFile->
log.info("Request XML file to Send :" + wsdlFile)
//Calling the function to hit the service
sendRequest(wsdlFile,iface,Operation,Report_File_LOC,requestXML,responseActual,propData)
reportFilewriter.flush()
}
}
}
//removing Interface created
removeInterface(wsdl)
log.info("Removed iface : " + wsdl)
reportFilewriter.flush()
}
Thanks,
Hanumant