How to read full DOM source including frames in Electron? - dom

I can't figure out how to get access to the full source of the HTML page including iframes. It should be similar to what we see in DevTools > Elements, but via Electron.
By source I mean either text representation of the DOM (including content of all iframes on the page), or the list of all elements and having a way to get access to their text-representations.
Any help is highly appreciated! Thanks.

If you're just looking to get a string of all the HTML, you can do so via the executeJavaScript API:
const {app, BrowserWindow, dialog} = require('electron')
async function createWindow () {
const mainWindow = new BrowserWindow()
await mainWindow.loadFile('index.html')
const result = await mainWindow.webContents.executeJavaScript("document.documentElement.outerHTML");
dialog.showMessageBox(mainWindow, {
message: result
});
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
For an HTML page like:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="./styles.css" rel="stylesheet">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
<iframe src="https://google.com/chrome"></iframe>
</body>
</html>
You'll get a dialog like this:
It is not however possible to just grab DOM elements in the main process that you can manipulate.

Related

Obtaining a json return for html editor in FileMaker

I'm using the summernotes html form on a FileMaker solution to write emails. originally I had a save button to transfer the html uri into a field and then email that with the client scripts. However, users (and me...) don't like having to click "save" and then "send".
I'm wondering if anyone has any ideas on how to automate this. I tried to set the save function on a 1 second recurrence, however, that stops typing and removes the cursor. I'm thinking either someway to pull data via json or ideally some way I can interrogate it with my FileMaker 'send' script?
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML Editor</title>
<!-- include libraries(jQuery, bootstrap) -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- include summernote css/js -->
<script src="https://cdn.jsdelivr.net/npm/summernote#0.8.16/dist/summernote.min.js"></script>
<!-- <link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.11/summernote.css" rel="stylesheet"> -->
<link href="https://cdn.jsdelivr.net/npm/summernote#0.8.16/dist/summernote.min.css" rel="stylesheet">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script>
var intervalID;
function autoSave() {
intervalID = setInterval(saveText, 1000);
}
function saveText() {
//$('#summernote').summernote('code', 'code');
//window.alert('save changes');
/* Prep the URL to use for the hand-off to FM. */
var fullURL = '[[SAVEURL]]&param=' + encodeURIComponent ($('#summernote').summernote('code'));
/* Send the data to FM. */
window.location = fullURL;
return false;
}
</script>
</head>
<body onload ="autoSave();">
<div id="summernote">[[CONTENT]]</div>
<script>
}
$(document).ready(function() {
$('#summernote').summernote({
height: 300,
tabsize: 2,
toolbar: [
// [groupName, [list of button]]
['style', ['style','bold', 'italic', 'underline', 'clear']],
//['font', ['strikethrough', 'superscript', 'subscript']],
//['fontsize', ['fontsize']],
['color', ['color']],
//['para', ['ul', 'ol', 'paragraph']],
//['height', ['height']],
['insert', ['link']],
//['insert', ['link','hr','table']],
//['misc',['codeview']],
['mybutton',['save']]
],
buttons: {save: SaveButton}
});
});
</script>
</body>
</html>
Instead of passing the encoded HTML as a parameter in the URL (&param=...) - which causes the page to reload and thus causes the focus to be lost - try passing the parameter as an anchor (#...).
Like that the page won’t reload, and the focus should remain. Of course, you’ll have to adjust your parameter reading code accordingly.
Alternatively, if you have FileMaker 19 you can use the FileMaker.PerformScript or FileMaker.PerformScriptWithOption function to pass the value directly to a script.

Flutter : Use Froala-editor in Flutter web

I wanted to use a rich text editor in flutter web, but I could not find anything like that in flutter web. So I thought If I could implement the froala-editor in flutter web. So is there any possibility of inserting the froala-editor javascript library to flutter web.
https://froala.com/wysiwyg-editor/
Is it possible to use froala-editor in flutter web or Is there anythings else possible to get a rich text editor in flutter web?
Thanks in advance.
Yes it is possible mate! But you can use this as a temporarily until Flutter web goes stable.
The Hack is you can have that froala or Quill any editor in plain html and you can render it in Flutter IFrame element and you can pass the data via Js Connector vice versa.
Here Example Code :
import 'dart:js' as js;
js.JsObject connector;
js.IFrameElement element;
String createdViewId = 'map_element';
js.context["connect_content_to_flutter"] = (js.JsObject content) {
connector = content;
};
element = html.IFrameElement()
..src = "/assets/assets/editor.html"
..style.border = 'none';
ui.platformViewRegistry
.registerViewFactory(createdViewId, (int viewId) => element);
// SO the above code defines your plain html(Place inside the Project folder ex:assets/editor.html) and registered with UI, now you can use the HTMLElementView(Widget) to render the view in screen.
HtmlElementView(
viewType: createdViewId,
);
// Now in your html file
<!DOCTYPE html>
<html>
<title>Sample</title>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css">
<link href="https://cdn.jsdelivr.net/npm/froala-editor#3.1.0/css/froala_editor.pkgd.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form method="post">
<textarea id='edit' style="margin-top: 30px;"></textarea>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/froala-editor#3.1.0/js/froala_editor.pkgd.min.js"></script>
<style>
span.fr-emoticon{
background-repeat: no-repeat !important;
font-size: 28px;
}
</style>
<script>
(function () {
new FroalaEditor("#edit", {
theme: 'royal',
height: 450
})
})()
parent.connect_content_to_flutter && parent.connect_content_to_flutter(window)
function getValue(){
return $('#edit').val();
}
window.addEventListener("message", (message) => {
if (message.data.id === "value") {
quill.root.innerHTML = message.data.msg;
}
})
</script>
</body>
</html>
// Above parent connect to flutter is very important line that you should include because that is the one connecting to flutter and the window listener is listening for sending the data from flutter.
//so in your dart
connector.callMethod(
'getValue',
) as String;
element.contentWindow.postMessage({
'id': 'value',
'msg': "Hi /n Welcome <b>sending data from dart</b>",
}, "*");
Yeah good to go.Happy coding !

how to integrate sailsjs with vuetify?

I am trying to use vuetify component like tables in my sails project. I can get the UI working fine, but all actions (button clicks) are not working unless I disable parasails for that page. Anyone has experience integrating sails with vuetify?
I followed this example:
https://github.com/ndabAP/vue-sails-example
But instead of using vue-bootstrap I did with Vuetify with the vue-cli:
vue create frontend
cd frontend
vue add vuetify
And in the vue.config.js I used:
// frontend/vue.config.js
outputDir: "../backend/assets/dependencies",
In the backend generate a controller route to index.js:
// config/routes.js
'/*': { action:'index', skipAssets: true, skipRegex: /^\/api\/v1\/.*$/ },
with the content:
// controllers/index.js
module.exports = {
friendlyName: 'View homepage',
description: 'Display homepage view',
exits: {
success: {
statusCode: 200,
description: 'Display the view index page.',
viewTemplatePath: 'pages/index'
},
},
fn: async function () {
return {};
}
};
The view layouts/layout.ejs should content:
<% /* views/layouts/layout.ejs */ %>
<!DOCTYPE html>
<html>
<head>
<title><%=typeof title == 'undefined' ? 'New Sails App' : title%></title>
<!-- Viewport mobile tag for sensible mobile support -->
<meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge">
<meta name=viewport content="width=device-width,initial-scale=1">
<link rel=icon href=/favicon.ico>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<!--STYLES-->
<!--STYLES END-->
</head>
<body>
<noscript>
<strong>We're sorry but frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id=app></div>
<!--TEMPLATES-->
<!--TEMPLATES END-->
<%- exposeLocalsToBrowser() %>
<!--SCRIPTS-->
<!--SCRIPTS END-->
</body>
</html>
And that is the better way that I figured it out. If there is another simplest way I want to know, because I think that is necessary modifying parasails.js to upload components directly or change the form of registering pages by registering components instead, using a unique page in a similar way.

getJSON - Loading Image Gallery From Public Server - Flickr

I have tried so many URL variations for Flickr and all attempts have failed to load my image gallery into my own webpage.
I am pretty sure its the URL. If I replace the URL with:
"api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?"
all works fine to load public photos from Flickr, but to load my own album (URL below), it won't work.
Yes I have a valid API from Flickr. I also checked the script syntax in "jsbin.com" and all of that is good.
Can anyone help resolve this?
Here is the jQuery script:
(function() {
var flickerUrl = "https://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=<removed by edit>&user_id=135938131#N02&format=json&jsoncallback=?";
$.getJSON(flickerUrl)
.done(function(data) {
$.each(data.items, function(i, item) {
var image = $("<img>")
.attr("src", item.media.m)
.attr("title", item.title);
$("<a>")
.attr("href", item.link)
.attr("target", "_blank")
.html(image)
.appendTo("#images");
if ( i === 8 ) {
return false;
}
});
});
})
();
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Flickr Image Gallery</title>
<link rel="stylesheet" href="css/main.css" />
</head>
<body>
<h1>Natural Scenery</h1>
<br>
<div id="images"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="./js/flickrgallery.js"></script>
</body>
</html>

Jquery mobile form response page does not download content from pageinit until refresh of page

I am new to jquery mobile, and am having problems getting content I have inserted dymically using pageinit to display on the first time of the form response page. It displays on subsequent refreshes of the page. I also don't want the content to cache.
I need to use querystring values like ?blah=1&blah=2 as I use these in my call to an external json file.
How should I be doing this? If I use rel="external", and setting ajax to false, I have problems with issues on android. So using pageinit in the header, how do I make the dynamically loaded content (in the example, the time in seconds) in the 2nd page display first time round?
I have simplified the problem into test pages below.
Expected behaviour. When you click on the submit button of the form you go through to the 2nd page which should display the no of seconds taken from datetime
Actual behaviour. The seconds/time does not display on the 2nd page until the page is refreshed.
Elsewhere, I have come across the suggestion to put the pageinit code into the div itself, however this has caused the content to cache on android (ie the no of seconds remains the same), so I don't want to do this.
Any ideas on how I should approach this would be much appreciated
Sample code
=======
Page 1 - form
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
<script src="/scripts/myinit.js"></script>
</head>
<body>
<div data-role="page" id="page1" data-add-back-btn="true">
<div data-role="content" data-theme="b">
<form action="page_2.htm" method="GET" id="form1" name="form1">
<input type="hidden" name="seconds" value="">
<div class="ui-block-b"><button type="submit" data-theme="a">Submit</button></div>
</form>
</div>
</div>
</body>
</html>
===
Page 2 form response page
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
<script src="/scripts/myinit.js"></script>
</head>
<body>
<div data-role="page" id="page2" data-add-back-btn="true">
<div id="job" data-role="content">
</div>
</div>
</body>
</html>
===
custom javascript file called /scripts/myinit.js (included in both pages above)
$('#page1').live('pageinit', function(event) {
var seconds = new Date().getTime();
$('input[name=seconds]').val(seconds);
});
$('#page2').live('pageinit', function(event) {
var querystring = location.search.replace( '?', '' ).split( '&' );
var queryObj = {};
for ( var i=0; i<querystring.length; i++ ) {
var name = querystring[i].split('=')[0];
var value = querystring[i].split('=')[1];
queryObj[name] = value;
}
var seconds = queryObj["seconds"];
$('#job').append("seconds=" + seconds);
});
try changing pageinit by pageshow. i had the same problem and it worked for me
Link to the external file like this:
HTML --
I'm a Link
JS --
$(document).delegate('#external-link', 'click', function () {
$.mobile.changePage('/path/to/file.html', { reloadPage : true });
return false;
});
Setting the reloadPage option for the changePage() function will allow the external page to be refreshed rather than loading the cached version. Since the external page will be refreshed, the pageinit code for it will run when it's initialized and your code should function properly.
Documentation: http://jquerymobile.com/demos/1.1.0-rc.1/docs/api/methods.html