SmartBlocks icon indicating copy to clipboard operation
SmartBlocks copied to clipboard

Iframe selector - choose iframe/Iframly, open in sidebar v1.3

Open fbgallet opened this issue 3 years ago • 5 comments

📌 Import the JSON file below in your graph to be sure to preserve the code structure

iframe selector v1.3.zip

📋 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

/* 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)

image)

fbgallet avatar Mar 21 '21 16:03 fbgallet

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 <--'

kmaustral avatar Mar 22 '21 02:03 kmaustral

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.

fbgallet avatar Mar 22 '21 08:03 fbgallet

I have added a link to the JSON file for better support of the code structure.

fbgallet avatar Mar 22 '21 08:03 fbgallet

Thanks. It works fine now. It seems like Roam is becoming more and more like a browser.

kmaustral avatar Mar 22 '21 09:03 kmaustral

New version, v1.1, with some fixes has been pushed up

fbgallet avatar Mar 27 '21 10:03 fbgallet