Jump to content

barchiel33

Members
  • Posts

    20
  • Joined

  • Last visited

  • Days Won

    1

barchiel33 last won the day on August 2

barchiel33 had the most liked content!

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

barchiel33's Achievements

  1. Hello @Jose Leviaguirre! Thank you for the response, I appreciate the information. Also thank you for making the modification to the article! However, the font size and other attributes can't be overridden using the snippet you show in your comment (at least it doesn't work for me). Applying the style to the parent element only affects elements that don't have their own styles applied. When you insert a Spotfire action control, the Spotfire javascripting seems to apply it's own styles directly to that control, overriding the parent element's styling. I suppose you could individually style each action control using the "Format..." interface, but that's fairly limited in what you're able to do and would require doing it for each control. I've attached a screenshot showing how, even with the styling snippet, the action control's icon's text is a different size.
  2. @apreble That's great to hear! I'm glad I was able to help :) The Spotfire articles section honestly needs some coding guidelines/standards, alot of the code there is either 1) outdated, 2) messily written, 3) contains syntax mistakes, or 4) some combination of the previous three, especially when it comes to the Javascripting/HTML. I hope they have plans to implement some kind of code review for articles. I know alot of people come to the articles thinking they can copy and paste the code with a few small tweaks, but they're more like case studies that tell you potential things you can do and give you an idea how to implement them.
  3. Hmm, so it looks like the article's script doesn't take into account having nested links (ie. <a><SpotfireControls id=blahblahblah></a> where the Spotfire control is a Link action control). So what's happening is that it's moving the link action control up out of the parent <a>. So this HTML: <div class="iconMenu" style="background:yellow;color:blue;font-size:50px;"> <a><SpotfireControl id="7f4b2b132dc244a8b29b58297d16a13f" /></a> <a>Action Control Link 2</a> <a>Action Control Link 3</a> <a>Action Control Link 4</a> <a>Action Control Link 5</a> <a>Action Control Link 6</a> <a>Action Control Link 7</a> <a>Action Control Link 8</a> <a>Action Control Link 9</a> <a>Action Control Link 10</a> <a>Menu</a> </div> <img class="icons fa-solid fa-1, fa-solid fa-2,fa-solid fa-3,fa-solid fa-4,fa-solid fa-5,fa-solid fa-6,fa-solid fa-7,fa-solid fa-8,fa-solid fa-9, fa-solid fa-0, fa-solid fa-bars"/> Becomes this: <div class="iconMenu" style="background:yellow;color:blue;font-size:50px;"> <a class="fa-solid fa-1"></a> <a id="7f4b2b132dc244a8b29b58297d16a13f" href="javascript:void(0);" class="fa-solid fa-2" title="Home"> //This is the Spotfire Link action control. <a class="fa-solid fa-3">Action Control Link 2</a> <a class="fa-solid fa-4">Action Control Link 3</a> <a class="fa-solid fa-5">Action Control Link 4</a> <a class="fa-solid fa-6">Action Control Link 5</a> <a class="fa-solid fa-7">Action Control Link 6</a> <a class="fa-solid fa-8">Action Control Link 7</a> <a class="fa-solid fa-9">Action Control Link 8</a> <a class="fa-solid fa-0">Action Control Link 9</a> <a class="fa-solid fa-bars">Action Control Link 10</a> <a class="undefined">Menu</a> //Since the Spotfire control 'stole' one of the icons, this becomes undefined, since there are 12 elements and only 11 icon classes. </div> The easiest solution is to remove the container <a> around the Spotfire Link action control. However, there is some base styling applied to Link action controls, and, unfortunately, the styles are inline instead of in a style sheet. So you'd need to use !important to override them. The most notable is the font size, but there are a few others. A potential alternative would be to extract the action controls to their own hidden container and just use the icons as facades, but that would take a good bit more work. I went through and rewrote the code to implement the overriding the font-size but also to implement some general best practices (such as using var when setting variables, checking that elements exist, etc.): var spaceBetweenLayers = 100; var itemsPerLayer = 1; var startingAngle = 0 var endingAngle= 120 var canvasPos = document.querySelector('[class^="sfx_canvas"]').getBoundingClientRect() ; var iconMenu = document.querySelector(".iconMenu"); if (iconMenu) { var iconMenuStyle = iconMenu.style; var backgroundColor= iconMenuStyle.background || "#fff"; var foregroundColor = iconMenuStyle.color || "navy"; var fontSize = iconMenuStyle.fontSize || "20px"; var style = ` <link href='https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.4.1/css/simple-line-icons.css' rel='stylesheet' ></link> <link href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css' rel='stylesheet'/> <style> .iconMenu { position: fixed; top:${canvasPos.y+15}px; left:${canvasPos.x+15}px; z-index:1; height:0; } .iconMenu a { font-size: ${fontSize} !important; position: fixed; display: flex; justify-content: center; align-items: center; text-decoration:none !important; cursor: pointer; /*animation*/ transition-timing-function: cubic-bezier(0,0,0,1); transition-duration: .25s; /*size and shape*/ width: ${fontSize}; height: ${fontSize}; padding: calc(${fontSize}/3); border-radius: 100%; /*colors*/ color:#747880 !important; background-color: ${backgroundColor}; box-shadow: 0 4px 18px #0000001a,0 4px 5px #0000001a; } .iconMenu a:last-child{ opacity:100% } .iconMenu a:hover{ color: #8498fa !important; } </style> `; iconMenu.insertAdjacentHTML("afterend",style); //script var timeOutPID = 0; var menuLinks = document.querySelectorAll(".iconMenu a") if (menuLinks) { var boxShadow = document.querySelector(".iconMenu a").style.boxShadow; function hover() { let gap = spaceBetweenLayers; let elements = document.querySelectorAll(".iconMenu a"); if (elements) { elements.forEach((e, i) => { if(i==elements.length-1) return; let angle = (endingAngle / itemsPerLayer) * (i%itemsPerLayer) + startingAngle; i%itemsPerLayer||(gap+=spaceBetweenLayers); e.style.transform = `rotate(${angle}deg) translate(${gap}px) rotate(-${angle}deg)`; e.style.boxShadow=boxShadow; e.onmouseover = resetDelayClose; e.onmouseout = delayClose; }); resetDelayClose(); } } function close(){ let elements = document.querySelectorAll(".iconMenu a"); if (elements) { elements.forEach((e, i) => { if (i==elements.length-1) return; e.style.transform = `translate(0px)`; e.style.boxShadow = "unset"; }); } } function delayClose(){ timeOutPID = setTimeout(close,1234); } function resetDelayClose(){ timeOutPID && clearTimeout(timeOutPID); } document.querySelector(".iconMenu a:last-child").onmouseover = hover; document.querySelector(".iconMenu a:last-child").onmouseout = delayClose; //setup icons on links var icons = document.querySelector(".icons").classList.value.split(","); icons[0] = icons[0].replace("icons ",""); menuLinks.forEach((e,i)=>{ e.className = icons[i]; e.title = e.innerText; e.innerText = ""; }); hover(); delayClose(); }; }; The HTML for this method would look like this: <div class="iconMenu" style="background:yellow;color:blue;font-size:50px;"> <SpotfireControl id="7f4b2b132dc244a8b29b58297d16a13f" /> <a>Action Control Link 2</a> <a>Action Control Link 3</a> <a>Action Control Link 4</a> <a>Action Control Link 5</a> <a>Action Control Link 6</a> <a>Action Control Link 7</a> <a>Action Control Link 8</a> <a>Action Control Link 9</a> <a>Action Control Link 10</a> <a>Menu</a> </div> <img class="icons fa-solid fa-1, fa-solid fa-2,fa-solid fa-3,fa-solid fa-4,fa-solid fa-5,fa-solid fa-6,fa-solid fa-7,fa-solid fa-8,fa-solid fa-9, fa-solid fa-0, fa-solid fa-bars"/> You'd just replace each <a>Action Control Link #</a> with a Spotfire Link action control with the desired title.
  4. Hello Vincent! Like many things in Spotfire, you could accomplish this with JavaScript. The canvas has an element associated with it, you could querySelector it and change it's background style like any other HTML element. If you leave the visuals with a transparent background, you wouldn't need to change them. Not 100% sure on the exact coding you'd have to write, you may need something like a mutation observer in case Spotfire has some looping code to set the canvas or something.
  5. Hello Maureen! I think you might be able to do it via Javascript. In the dev tools, you can see the element corresponding to the column header. I'd imagine you could use a javascript function to find each header you want to add a tooltip to and attach a tooltip that shows on the mouse over event.
  6. Yep, I mentioned that in my post although I called it the wrong thing. I said Canvas Layout when I meant Page Layout.
  7. Yep! This is entirely possible! Basically what you do is rebuild the page layout each time a visual is added or removed. Here's a good starting point: you'll use similar code to this. Basically, iterate through the visuals on the page and add them to the layout in different places based on their names.
  8. The issue is that you're using a table for your layout instead of one of the more responsive layout methodologies. Look into switching to a grid or a flexbox layout. With both of those, you can have either the entire container or each individual element shrink or grow based on the viewport. It also seems like you've changed the canvas layout for this page, otherwise it wouldn't scroll. I would suggest you look into using some other content styling, such as a collapsible accordion, to reduce the necessary height and to also reduce the white space. For example, you could combine first and second columns of your current layout into a single column with an accordion.
  9. I'm willing to bet the issue is the public key token. I suspect that when the script runs on the original, it adds the reference is essentially duplicating the original script dll into a folder either in your computer or in the Spotfire files. Then when you move your report, it tries to repeat that process but it can't make a new copy since the public key token is specified, causing it to error out. Have you tried having someone who has never opened the original template open the copy in its new folder and run the script? Alternatively, if you have the file for the reference you're trying to add, you could add the folder it's contained in to your sys path and then add the dll by file name. If the script runs after doing this, then that would be clear proof to me that it is what I suspected. This would only work as a debug test, since other users wouldn't be able to access the dll file location (unless it's on a network drive or something). But it would help determine the exact cause. import sys import clr sys.path.append('C:\PathToDllFolder') clr.AddReference('MyDll.dll')
  10. You could also use a combination of a Python/TERR data function and your Ironpython script. Have the data function trigger automatically and when setting the input parameters make sure to include the filter scheme you're using. All this function would need to do is output a count of the rows in one of your columns, preferably a unique identifying column. Alternatively, you could have it just output the current system time. Either method should work fine. Then you can have your Ironpython script trigger off that document property. Assuming you go with a TERR function, you could create a data function with one input called input_col and one output called output. input_col would be of type column and allow any data type. output would have the Value type. The script would be: output <- Sys.time() You don't actually need to use the input_col here, it's just there to trigger the function. I think the system time should trigger the document property's change event, even if the data function triggers back to back in quick succession. I'd have to test to be sure, but I think it'd work even at the seconds level so if someone changed the filter and then immediately changed it again, it should still fire the change event.
  11. There should be a way to do this using Javascript. You should be able to target the visualizations container element and set it's position to sticky. Not sure the exact coding though. I believe you'll want to use a query selector for the sf-visual-id attribute, since that value doesn't seem to change (whereas the element's id value does). The part I'm iffy on is getting the position to switch from absolute to sticky and stay on sticky. There might be some javascript that's part of the Spotfire built-in scripting that keeps the position property from changing for whatever reason.
  12. Hi @pratikpathak, so you have a set of transformations and in the titles are basically flags indicating which to apply? Something like FebData_DateFilter_ConvertToHours_FactoryFilter.csv? When do you apply the transformations? Ex. Right when you load the data, later when you merge data, etc. etc. Have you used Ironpython before?
  13. yes, that should be possible although it depends a bit on how you added (or add) the CSVs. I'm not sure the exact code off the top of my head, but you should be able to use Ironpython to iterate over your CSVs (either when using Ironpython to load the CSVs or by iterating over the data sources in the report and checking their type). As you iterate, you can use either an If elif or extract whatever transformation from the file name. Then Ironpython has ways to add/remove/change transformations to data tables. Here are some example scripts that may give you a good starting point:
  14. Ahhh, authentication is tricky within Spotfire. I'm not 100% certain about this, but I believe that Python data functions have an 'issue' with HTTPS (and similar REST/Web requests) in Spotfire. I'm guessing it's probably a security thing or something. You might be able to accomplish what you want via IronPython instead, have you given that a try? I managed to find this script: but I can't vouch for its effectiveness since I haven't tried it before. Could you tell me which library you're trying to use?
  15. I'm thinking you'd have an easier time using a Python data function for what you're trying to do. I would think something like: li = list(search_list.split(', ')) output = text_column.apply(lambda row: all(x in row for x in li)) where search_list is a string document property containing a comma-space separated list of the terms to seach for, text_column is a column from the data table that you want to search for the terms, and output is a column output which will contain true if all terms in search_list are in the corresponding row from the text column and false if any term isn't.
×
×
  • Create New...