I'm writing a Chrome extension that will pass data from a webpage to a file and download it. Ultimately, the file ends up in Obsidian for easy note-taking. The extension works fine most of the time, as long as all the fields exist, so I've started introducing some code for when those elements don't exist.
For example, this is the original code:
const ogImage = document.querySelector('meta[property="og:image"]');
const og_image = ogImage.content;
That works fine until the og:image tag doesn't exist in the page. This is the code I came up with to handle the problem:
const ogImage = document.querySelector('meta[property="og:image"]');
if (ogImage != "") {
const og_image = ogImage.content;
console.log(og_image);
} else {
const og_image = "https://---/vvMtZvn.jpg";
console.log(og_image);
};
Depending on the page, the console will output the correct value. However, I get errors if I try to use the value outside of this code. The console in the following block replies with: Uncaught ReferenceError: og_image is not defined
const ogImage = document.querySelector('meta[property="og:image"]');
if (ogImage != "") {
const og_image = ogImage.content;
} else {
const og_image = "https://i.imgur.com/vvMtZvn.jpg";
};
console.log(og_image);
I've been searching but can't find an answer. Maybe I'm asking the wrong question. Any help would be appreciated.
Please try this.
let og_image;
const ogImage = document.querySelector('meta[property="og:image"]');
if (ogImage != null) {
og_image = ogImage.content;
console.log(og_image);
} else {
og_image = "https://---/vvMtZvn.jpg";
console.log(og_image);
};
Related
I'm working on a site that takes fairly long to build/deploy. I sometimes need information that is only available server-side for debugging. Using console.log is annoying since adding a console.log in the code and building takes too long.
But I also don't want the site to always log that information to the console.
My plan was to have a wrapper function for console.log, that checks if there is e.g dev_config set in localStorage.
For example to activate certain verbose levels that then show respective logs, or log only in certain sections.
Would this have a significant impact on performance of the site?
For instance something like this:
const devLog = (message) => {
devConfig = JSON.parse(localStorage.getItem('dev_config'))
if (devConfig != null) {
// ...
// other checks (set devMode to true)
// ...
if (devMode === true) {
const now = new Date()
const hours = now.getHours()
const min = (now.getMinutes() + '').padStart(2, '0')
const sec = (now.getSeconds() + '').padStart(2, '0')
console.log(`[${hours}:${min}:${sec}] `, message)
}
}
}
PS: I am aware of the built-in browser dev tools and I am using them in most cases. But since the information in my current problem is server side, I don't think I can get with the dev tools what I need.
You could overwrite console.log but that could annoy you later on. I prefer to have my own logger like your devLog function. It's more explicit.
As #Barmar suggested in the comments you could instead check the localStorage on load instead of on every call. I have something similar to the below in a few projects of mine:
{
let devConfig = JSON.parse(localStorage.getItem('dev_config'));
devLog = (...args) => {
if (devConfig) {
const time = new Date().toLocaleTimeString()
console.log(`[${time}] `, ...args)
}
};
devLog.activate = () => {
devConfig = true;
localStorage.setItem('dev_config', true)
}
devLog.deactivate = () => {
devConfig = false;
localStorage.setItem('dev_config', false)
}
devLog.toggle = () => {
if ( devConfig ) {
devLog.deactivate()
} else {
devLog.activate()
}
}
}
Since when you're reading dev_config from the localStorage for the first time you'll get null it will start off deactivated - which seems like a good default to me.
I'm new to Google Docs scripting, and am following this tutorial in order to create Google docs from a template and a Google sheet. I've written everything as the tutorial specifies - here's the entirety of my code:
function onOpen() {
const menu = SpreadsheetApp.getUi().createMenu('Create Review Forms');
menu.addItem('Create Review Forms', 'createNewGoogleDocs');
menu.addToUi();
}
function createNewGoogleDocs() {
const googleDocTemplate = DriveApp.getFileById('1JqwXS_yOo_v2CV5akOf26tQnj-AdB3cvrVmxTn10lZI');
const destinationFolder = DriveApp.getFolderById('1ZFaHXonRQZ-2S5YGj5vCRu_r23vWoVod');
const rows = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getDataRange().getValues();
Logger.log(rows)
rows.forEach(function(row, index){
if (index === 0) return;
if (row[6]) return;
const copy = googleDocTemplate.makeCopy(`${row[1]} ${row[2]} application`, destinationFolder);
const doc = DocumentApp.openById(copy.getId());
const body = doc.getBody();
body.replaceText('{{Cand Number}}', row[0]);
body.replaceText('{{Resume}}', row[1]);
body.replaceText('{{Essay 1}}', row[2]);
body.replaceText('{{Essay 2}}', row[3]);
body.replaceText('{{Essay 3}}', row[4]);
doc.saveAndClose();
sheet.getDataRange(index + 1, 6).setValue(doc.getUrl());
})
}
It works insofar as a menu option is created as specified in the onOpen function. However, every time I try to run or debug the whole thing, I get this "Unknown error" in the execution log:
This started even after I wrote the first couple of lines in the lower function, but even when I comment them out the Unknown Error persists. I'd appreciate any help anyone can offer!
I'm new on electronjs and developing a small application that reads a json file and build a small html form and return the values entered by the user.
So I've developed small scripts in javascript that link to html 'button' tags to call dialogs so that a user can enter directories, files and save the final form. Everything works nicely... on electronjs "^3.1.13". But if I'm updating to a recent version of the lib ("^8.2.5"), then all my cool ShowOpenDialog don't work at all. Any clue of what happens?
Here is the script to open a folder if it helps:
{
let myName = document.currentScript.getAttribute('name');
const ipc = require('electron').ipcRenderer;
let asyncBtn = document.querySelector('#folder-selector-'+myName);
let replyField = document.querySelector('#folder-selector-content-'+myName);
let onButtonClick = function() {
const { dialog } = require('electron').remote;
let dialogOptions = {
title: "Choisir un dossier:",
properties: ['openDirectory','promptToCreate'],
};
dialog.showOpenDialog(
dialogOptions,
fileNames => {
if (fileNames === undefined) {
console.log("No file selected");
} else {
console.log('file:', fileNames[0]);
replyField.value = fileNames[0];
}
})
};
asyncBtn.addEventListener("click", onButtonClick);
}
Thanks a lot for any help.
Apart from the fact that the call to dialog.showOpenDialog has indeed been updated in recent versions of Electron, and returns a promise instead of making use of a callback function, there is another flaw in your updated code: reading the above-mentioned documentation page shows that getCurrentWindow() is not a method of dialog; it can be obtained from remote instead, so you have to add it explicitely:
const { dialog, getCurrentWindow } = require('electron').remote;
then simply call it from inside dialog.showOpenDialog:
dialog.showOpenDialog( getCurrentWindow(), dialogOptions).then(result => {
but this is an error you could have caught yourself by looking at the DevTools's console, which would display:
TypeError: dialog.getCurrentWindow is not a function
Recent version of showOpenDialog receives two arguments: optional BrowserWindow, and options as second argument. It returns promise and not requires callback.
https://github.com/electron/electron/blob/8-x-y/docs/api/dialog.md#dialogshowopendialogbrowserwindow-options
So you need to change you callback logic to promises.
let onButtonClick = function() {
const { dialog } = require('electron').remote;
let dialogOptions = {
title: "Choisir un dossier:",
properties: ['openDirectory','promptToCreate'],
};
dialog.showOpenDialog(
dialogOptions
).then((fileNames)=>{
if (fileNames === undefined) {
console.log("No file selected");
} else {
console.log('file:', fileNames[0]);
replyField.value = fileNames[0];
}
}).catch(err=>console.log('Handle Error',err))
};
asyncBtn.addEventListener("click", onButtonClick);
thanks a lot Vladimir. So I've tried to update my code as explained, updating electron package to version 8.2.5 and modifying the script as you explained but it's not going any better. If I got it well, this code should be correct, but doesn't work on electron 8.2.5. Any error you still see on this?
{
let myName = document.currentScript.getAttribute('name');
const ipc = require('electron').ipcRenderer;
let asyncBtn = document.querySelector('#folder-selector-'+myName);
let replyField = document.querySelector('#folder-selector-content-'+myName);
let onButtonClick = function() {
const { dialog } = require('electron').remote;
let dialogOptions = {
title: "Choisir un dossier:",
properties: ['openDirectory','promptToCreate']
};
dialog.showOpenDialog( dialog.getCurrentWindow(), dialogOptions).then(result => {
if(!result.canceled) {
replyField.value = result.filePaths[0];
}
}).catch(err => {
console.log(err)
})
};
asyncBtn.addEventListener("click", onButtonClick);
}
Ok, finally got it. Apart from the most appreciated help I had, I missed
"webPreferences": {
nodeIntegration: true
}
in the main.js to make it work.
The discovering of the Developer Tools were of great help as well :)
Now everything is fine again. Thanks a lot!
I'm writing a restartless Firefoxextension where I have to enumerate all open tabs and work with them.
Here's the code-part that throws the error:
getInfoString : function ()
{
infos = "";
HELPER.alerting("url", "URL-Function");
var winMediator = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
HELPER.alerting("url", "Mediator initialized");
var mrw = winMediator.getEnumerator(null);
while(mrw.hasMoreElements())
{
var win = mrw.getNext();
var t = win.gBrowser.browsers.length;
HELPER.alerting("url", "browsers: " + t);
for (var i = 0; i < t; i++)
{
var b = win.gBrowser.getBrowserAtIndex(i);
if(b.currentURI.spec.substr(0,3) != "http")
{
continue;
}
HELPER.alerting(b.title,b.currentURI.spec);
var doc = b.contentDocument;
var src = doc.documentElement.innerHTML;
infos = infos + src
HELPER.alerting("doc", src);
}
}
return infos;
}
I have a JavascriptDebugger-Addon running while testing this and Firefox executes everything fine to the line
HELPER.alerting("url", "browsers: " + t);
But AFTER this line, the debugger-addons throws an error, saying that:
win.gBrowser is undefined
... pointing to the line:
var t = win.gBrowser.browsers.length;
But before it throws the error I get my alertmessage which gives me the correct number of tabs. So the error is thrown after the line was executed and not directly WHEN it was executed.
Does anyone has an idea how to fix this, because the extension stops working after the error has been thrown.
Greetz
P.S.: If someone has a better headline for this, feel free to edit it.
Using winMediator.getEnumerator(null) would give you all types of window, that may or may not be browser windows. You should try changing the following line
var mrw = winMediator.getEnumerator(null);
with
var mrw = winMediator.getEnumerator('navigator:browser');
I finally figured out that this behavior can happen sometimes.
I just rearranged the code a bit, removing some alerts inside the for-loop and it works just fine again.
So if someone has this error too, just rearrange your code and it should work like a charm again.
I have a Windows app that contains a browser control that loads pages from my website. However, due to the Windows app, I cannot debug Javascript in the usual ways (Firebug, console, alerts, etc).
I was hoping to write a jQuery plug-in to log to an external browser window such that I can simply do something like:
$.log('test');
So far, with the following, I am able to create the window and display the templateContent, but cannot write messages to it:
var consoleWindow;
function getConsoleWindow() {
if (typeof (consoleWindow) === 'undefined') {
consoleWindow = createConsoleWindow();
}
return consoleWindow;
}
function createConsoleWindow() {
var newConsoleWindow = window.open('consoleLog', '', 'status,height=200,width=300');
var templateContent = '<html><head><title>Console</title></head>' +
'<body><h1>Console</h1><div id="console">' +
'<span id="consoleText"></span></div></body></html>';
newConsoleWindow.document.write(templateContent);
newConsoleWindow.document.close();
return newConsoleWindow;
}
function writeToConsole(message) {
var console = getConsoleWindow();
var consoleDoc = console.document.open();
var consoleMessage = document.createElement('span');
consoleMessage.innerHTML = message;
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
consoleDoc.close();
}
jQuery.log = function (message) {
if (window.console) {
console.log(message);
} else {
writeToConsole(message);
}
};
Currently, getElementById('consoleText') is failing. Is what I'm after possible, and if so, what am I missing?
Try adding
consoleDoc.getElementById('consoleText');
right before
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
If the line you added is the one that fails, then that means consoleDoc is not right, if the next line is the only one that fails then ..ById('consoleText') is not matching up
If I don't close() the document, it appears to work as I hoped.