SmartBlocks
SmartBlocks copied to clipboard
Iframe selector - choose iframe/Iframly, open in sidebar v1.3
📌 Import the JSON file below in your graph to be sure to preserve the code structure
📋 Description:
Demo video: https://youtu.be/ZqwE4hhpbVM
Open an iframe embed of an URL in child block (and optionally in sidebar), allowing to choose beetwen different Iframely views or iframe Roam vanilla (see video above for examples):
- extract URL from current block (it can be simple link, or an alias, there can be some text around: the last URL is used),
- open a dialog box to choose the appropriate view (desappear after 5" if not focused: auto-confirm)
- create a child block with {{iframe: URL}} or {{iframely: URL}}, add eventually two other child blocks for iframely settings (view/summary, etc.)
- open sidebar with this new iframe block if checkbox is checked
- add an alias with iframe block-ref for quick overview or futur opening (with shift+click).
- add tag for default css of iframe block (can be disabled).
Default view is iframely default, as defined is [[roam/js/iframely]] settings. Other settings are available in the code block of the SmartBlock: force opening in sidebar, default string for the alias, default view, default css added to the iframe block.
v.1.3 May 23, 2021 New feature:
- support Iframely extension (see below in Prerequisites)
- dialog box allowing to select appropriate view
v1.1 March 27th 2021 Fixes:
- works with multiples urls in the block: open always last one
- works with collapsed children blocks (expand then add on top)
- unfocus at the end of the command (to avoid mishandling) New feature:
- add optionally #[[.iframe]] for formating (like reduce margin)
✅ Prerequisites or dependencies that are required for this SmartBlock
- Iframely extension from roamjs.com by David Vargas
- Roam42
- You can enable the following css (included in the JSON file):
- for resizing iframe to max width rather than 720px normal limit
/* Override image, iframe, pdf resize */
div[style*="width: 580px;"],
div[style*="width: 720px;"] {
width: 100% !important;
}
div[style*="height: 720px;"] {
height: 85vh !important;
}
- for reduced margin an no bullet, with #[[.iframe]] (adapt it to you theme)
#roam-right-sidebar-content .iframe .rm-block-main {
margin-left: -30px !important;
margin-right: -15px !important;
}
#roam-right-sidebar-content .iframe .rm-bullet {
visibility: hidden;
}
#roam-right-sidebar-content .iframe .rm-block__ref-count {
display: none;
}
💡 Additional Info
📌 Import the JSON file below in your graph to be sure to preserve the code structure iframe selector v1.3.zip
✂️ Code of the SmartBlock:
- #42SmartBlock iframe selector
- <%JA:```javascript
/******************************************************************
iframe Selector
Create {{iframe: }} or {{iframely: }} view in child block
Version: 1.3
Published: May 23, 2021
By: Fabrice Gallet
Twitter: @fbgallet
Support my work on: https://www.buymeacoffee.com/fbgallet
/************************* USER SETTINGS **************************/
let defaultMode = "iframely"; // change to "iframe" to create vanilla iframe by default
const iframeCSS = "#[[.iframe]]"; // change to "" for no CSS, or any other customized CSS
const aliasStr = "👁🗨 iframe"; // set alias for sneak peek in parent block
const withAlias = true; // change to false if you don't want alias link to iframe block
let openInSideBar = false; // change to true if you want, by default, opening the iframe in sidebar
/******************************************************************/
/* Function for extracting url from a text */
var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
function linkify(text) {
return text.match(urlRegex);
}
let dView = "default";
let pageUid = await roam42.common.getPageUidByTitle("roam/js/iframely");
let blockInfo = await roam42.common.getBlockInfoByUID(pageUid, true);
if (blockInfo !== null) {
if (blockInfo[0][0].children) {
if (blockInfo[0][0].children[0].children) {
dView = blockInfo[0][0].children[0].children[0].string;
}
}
}
const defaultView = dView;
var createIframeBlock = async function (parent, parentContent, link, mode, id, openSide) {
let modeTab = mode.split(" ");
mode = modeTab[0];
let view = defaultView;
if (modeTab.length > 1) { view = modeTab[1]; }
window.roamAlphaAPI.updateBlock({"block":
{"uid": id,
"string": " ",
"open": false}});
let iframeCommand = '{{' + mode + ': ' + link + '}} ' + iframeCSS;
if ((modeTab.length > 1) && (view != "default")) {
let currentBlockInfo = await roam42.common.getBlockInfoByUID(id, true);
if (currentBlockInfo[0][0].children) {
if (currentBlockInfo[0][0].children[0].string == "view") {
await roam42.common.updateBlock(currentBlockInfo[0][0].children[0].children[0].uid, view, true);
}
}
else {
await roam42.common.createBlock(id, -1, "view");
let childBlockInfo = await roam42.common.getBlockInfoByUID(id, true);
await roam42.common.createBlock(childBlockInfo[0][0].children[0].uid, -1, view);
}
} else if ((mode == "iframe") || (view == "default")) {
deleteChildBlocks(id);
}
await roam42.common.sleep(50);
window.roamAlphaAPI.updateBlock({"block":
{"uid": id,
"string": iframeCommand,
"open": false}});
let blockPlusAliasToIframe = parentContent;
if (withAlias && !existingIframe) {blockPlusAliasToIframe += " [" + aliasStr + "](((" + id + ")))";}
if (openSide) {
if (fromParent) {
window.roamAlphaAPI.updateBlock({"block":
{"uid": parent,
"string": blockPlusAliasToIframe,
"open": false}});
}
window.roamAlphaAPI.ui.
rightSidebar.addWindow({window:
{type:'block' ,'block-uid': id}});
}
else {
if (fromParent) {
window.roamAlphaAPI.updateBlock({"block":
{"uid": parent,
"string": blockPlusAliasToIframe,
"open": true}});
}
}
}
var deleteChildBlocks = async function (id) {
let currentBlockInfo = await roam42.common.getBlockInfoByUID(id, true);
if (currentBlockInfo[0][0].children) {
if (currentBlockInfo[0][0].children[0].string == "view") {
await roam42.common.deleteBlock(currentBlockInfo[0][0].children[0].children[0].uid);
await roam42.common.deleteBlock(currentBlockInfo[0][0].children[0].uid);
}
}
}
/* Extract url from current block (there must not be more than one url in the block, otherwise the different urls are concatenated) */
let startingBlockUID = roam42.common.currentActiveBlockUID();
let iframeMode = defaultMode;
let uid = startingBlockUID;
let blockContent = document.activeElement.value;
blockContent = blockContent.trim();
let exist = false;
let fromChild = false;
if (blockContent=="") { blockContent = await navigator.clipboard.readText(); }
else if (blockContent.search("{{iframe") != -1) {
fromChild = true;
exist = true;}
else {
let info = await roam42.common.getBlockInfoByUID(startingBlockUID, true);
if (info[0][0].children) {
let childContent = info[0][0].children[0].string;
if (childContent.search("{{iframe") != -1) {
exist = true;
uid = info[0][0].children[0].uid;
}
}
}
const fromParent = !fromChild;
const existingIframe = exist;
let urlsTab = linkify(blockContent);
let url = urlsTab[urlsTab.length - 1];
if (!existingIframe) {
uid = window.roamAlphaAPI.util.generateUID();
window.roamAlphaAPI.createBlock(
{"location":
{"parent-uid": startingBlockUID,
"order": 0},
"block":
{"string": ' ',
"uid": uid}});
}
createIframeBlock(startingBlockUID, blockContent, url, iframeMode, uid, false);
let checkState = '<input type="checkbox"';
if (openInSideBar) {checkState += ' checked="checked"';}
checkState += '>';
iziToast.info({
resetOnHover: true,
drag: false,
close: false,
overlay: false,
position: "center",
title: 'Iframe selector',
message: 'Open in sidebar ?',
inputs: [
[checkState, 'change', function (instance, toast, input, e) {
// console.log(input.checked);
}],
['<select><option value="iframely default">Default Iframely</option><option value="iframe">Vanilla iframe</option><option value="iframely summary">Iframely summary</option><option value="iframely card">Iframely card</option><option value="iframely iframe">Iframely iframe</option></select>', 'change', function (instance, toast, select, e) {
createIframeBlock(startingBlockUID, blockContent, url, select.options[select.selectedIndex].value, uid, false);
}, true]
],
buttons: [
['<button><b>Confirm</b></button>', function (instance, toast, button, e, inputs) {
// console.log('Second field: ' + inputs[2].options[inputs[2].selectedIndex].value);
// iframeMode = inputs[1].options[inputs[1].selectedIndex].value;
if (inputs[0].checked) {
createIframeBlock(startingBlockUID, blockContent, url, iframeMode, uid, inputs[0].checked);
}
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
}, false],
['<button><b>Cancel</b></button>', function (instance, toast, button, e, inputs) {
if (!existingIframe) {
window.roamAlphaAPI.updateBlock({"block":
{"uid": startingBlockUID,
"string": blockContent
}});
deleteChildBlocks(uid);
roam42.common.deleteBlock(uid);
}
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
}, false],
],
onClosing: function(instance, toast, closedBy){
},
onClosed: function(instance, toast, closedBy){
}
});
```%> <%NOBLOCKOUTPUT%>
- <%JA:```javascript
/******************************************************************
iframe Selector
Create {{iframe: }} or {{iframely: }} view in child block
Version: 1.3
Published: May 23, 2021
By: Fabrice Gallet
Twitter: @fbgallet
Support my work on: https://www.buymeacoffee.com/fbgallet
/************************* USER SETTINGS **************************/
let defaultMode = "iframely"; // change to "iframe" to create vanilla iframe by default
const iframeCSS = "#[[.iframe]]"; // change to "" for no CSS, or any other customized CSS
const aliasStr = "👁🗨 iframe"; // set alias for sneak peek in parent block
const withAlias = true; // change to false if you don't want alias link to iframe block
let openInSideBar = false; // change to true if you want, by default, opening the iframe in sidebar
/******************************************************************/
/* Function for extracting url from a text */
var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
function linkify(text) {
return text.match(urlRegex);
}
let dView = "default";
let pageUid = await roam42.common.getPageUidByTitle("roam/js/iframely");
let blockInfo = await roam42.common.getBlockInfoByUID(pageUid, true);
if (blockInfo !== null) {
if (blockInfo[0][0].children) {
if (blockInfo[0][0].children[0].children) {
dView = blockInfo[0][0].children[0].children[0].string;
}
}
}
const defaultView = dView;
var createIframeBlock = async function (parent, parentContent, link, mode, id, openSide) {
let modeTab = mode.split(" ");
mode = modeTab[0];
let view = defaultView;
if (modeTab.length > 1) { view = modeTab[1]; }
window.roamAlphaAPI.updateBlock({"block":
{"uid": id,
"string": " ",
"open": false}});
let iframeCommand = '{{' + mode + ': ' + link + '}} ' + iframeCSS;
if ((modeTab.length > 1) && (view != "default")) {
let currentBlockInfo = await roam42.common.getBlockInfoByUID(id, true);
if (currentBlockInfo[0][0].children) {
if (currentBlockInfo[0][0].children[0].string == "view") {
await roam42.common.updateBlock(currentBlockInfo[0][0].children[0].children[0].uid, view, true);
}
}
else {
await roam42.common.createBlock(id, -1, "view");
let childBlockInfo = await roam42.common.getBlockInfoByUID(id, true);
await roam42.common.createBlock(childBlockInfo[0][0].children[0].uid, -1, view);
}
} else if ((mode == "iframe") || (view == "default")) {
deleteChildBlocks(id);
}
await roam42.common.sleep(50);
window.roamAlphaAPI.updateBlock({"block":
{"uid": id,
"string": iframeCommand,
"open": false}});
let blockPlusAliasToIframe = parentContent;
if (withAlias && !existingIframe) {blockPlusAliasToIframe += " [" + aliasStr + "](((" + id + ")))";}
if (openSide) {
if (fromParent) {
window.roamAlphaAPI.updateBlock({"block":
{"uid": parent,
"string": blockPlusAliasToIframe,
"open": false}});
}
window.roamAlphaAPI.ui.
rightSidebar.addWindow({window:
{type:'block' ,'block-uid': id}});
}
else {
if (fromParent) {
window.roamAlphaAPI.updateBlock({"block":
{"uid": parent,
"string": blockPlusAliasToIframe,
"open": true}});
}
}
}
var deleteChildBlocks = async function (id) {
let currentBlockInfo = await roam42.common.getBlockInfoByUID(id, true);
if (currentBlockInfo[0][0].children) {
if (currentBlockInfo[0][0].children[0].string == "view") {
await roam42.common.deleteBlock(currentBlockInfo[0][0].children[0].children[0].uid);
await roam42.common.deleteBlock(currentBlockInfo[0][0].children[0].uid);
}
}
}
/* Extract url from current block (there must not be more than one url in the block, otherwise the different urls are concatenated) */
let startingBlockUID = roam42.common.currentActiveBlockUID();
let iframeMode = defaultMode;
let uid = startingBlockUID;
let blockContent = document.activeElement.value;
blockContent = blockContent.trim();
let exist = false;
let fromChild = false;
if (blockContent=="") { blockContent = await navigator.clipboard.readText(); }
else if (blockContent.search("{{iframe") != -1) {
fromChild = true;
exist = true;}
else {
let info = await roam42.common.getBlockInfoByUID(startingBlockUID, true);
if (info[0][0].children) {
let childContent = info[0][0].children[0].string;
if (childContent.search("{{iframe") != -1) {
exist = true;
uid = info[0][0].children[0].uid;
}
}
}
const fromParent = !fromChild;
const existingIframe = exist;
let urlsTab = linkify(blockContent);
let url = urlsTab[urlsTab.length - 1];
if (!existingIframe) {
uid = window.roamAlphaAPI.util.generateUID();
window.roamAlphaAPI.createBlock(
{"location":
{"parent-uid": startingBlockUID,
"order": 0},
"block":
{"string": ' ',
"uid": uid}});
}
createIframeBlock(startingBlockUID, blockContent, url, iframeMode, uid, false);
let checkState = '<input type="checkbox"';
if (openInSideBar) {checkState += ' checked="checked"';}
checkState += '>';
iziToast.info({
resetOnHover: true,
drag: false,
close: false,
overlay: false,
position: "center",
title: 'Iframe selector',
message: 'Open in sidebar ?',
inputs: [
[checkState, 'change', function (instance, toast, input, e) {
// console.log(input.checked);
}],
['<select><option value="iframely default">Default Iframely</option><option value="iframe">Vanilla iframe</option><option value="iframely summary">Iframely summary</option><option value="iframely card">Iframely card</option><option value="iframely iframe">Iframely iframe</option></select>', 'change', function (instance, toast, select, e) {
createIframeBlock(startingBlockUID, blockContent, url, select.options[select.selectedIndex].value, uid, false);
}, true]
],
buttons: [
['<button><b>Confirm</b></button>', function (instance, toast, button, e, inputs) {
// console.log('Second field: ' + inputs[2].options[inputs[2].selectedIndex].value);
// iframeMode = inputs[1].options[inputs[1].selectedIndex].value;
if (inputs[0].checked) {
createIframeBlock(startingBlockUID, blockContent, url, iframeMode, uid, inputs[0].checked);
}
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
}, false],
['<button><b>Cancel</b></button>', function (instance, toast, button, e, inputs) {
if (!existingIframe) {
window.roamAlphaAPI.updateBlock({"block":
{"uid": startingBlockUID,
"string": blockContent
}});
deleteChildBlocks(uid);
roam42.common.deleteBlock(uid);
}
instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
}, false],
],
onClosing: function(instance, toast, closedBy){
},
onClosed: function(instance, toast, closedBy){
}
});
```%> <%NOBLOCKOUTPUT%>
📷 Screenshot of the #42SmartBlock (note entire code)
)
Thank you (merci) Fabrice. This looks very useful. When I run it, I get the iframe but it doesn't open in the sidebar.
This is what I get in the sidebar: '--> Variable iframeRef not SET <--'
Hi @kmaustral , make sure that the two smartblock commands beetwen the two blocks of javascript are on their own line:
- <%CURRENTBLOCKREF:iframeRef%>
- <%SIDEBARWINDOWOPEN:<%GET:iframeRef%>%> (I will change the code screenshot for a better overview of the different bullets)
If it doesn't work, add perhaps some sleep time at the end of first javascript block.
I have added a link to the JSON file for better support of the code structure.
Thanks. It works fine now. It seems like Roam is becoming more and more like a browser.
New version, v1.1, with some fixes has been pushed up