4

I'm using this widget from tradingview (https://www.tradingview.com/widget/ticker/) and wanted to know if there is a way to:

  • a) make the ticker bar scroll (iFrame scrolling=yes)
  • b) re-size the widget.

I've not used iFrame before and am not sure how to go about making the customisations or if they are even possible.

Bharata
  • 13,509
  • 6
  • 36
  • 50
DanielSon
  • 1,415
  • 4
  • 27
  • 40

4 Answers4

12

Here's an answer that achieves the desired effect: https://codepen.io/epsilon42/pen/BPZgjP/

It involves mainly the use of CSS animations but it was also necessary to add some jQuery to clone the iframe to get rid of the gap when the ticker runs to the end. This was the only way I could think of doing it due to being unable to manipulate contents of an iframe cross-domains.

I had to remove the async on the TradingView script in order for the $( document ).ready to fire correctly.

Another thing to note is that it is necessary to change the width in the CSS according to how many items you choose to have inside the ticker:

.ticker-canvas {
  width: calc((200px * 15) + 2px);
}

Change the value 15 in the above CSS to the number of items you call in the script. 200px seems to be the minimum width you can use before the widget decides to get rid of items automatically, but there doesn't seem to be any problem with using a higher value if desired. 2px is to account for the 1px border either side of the widget.

HTML:

<!-- TradingView Widget BEGIN -->
<div class="ticker-container">
<div class="ticker-canvas">
<div class="tradingview-widget-container">
  <div class="tradingview-widget-container__widget"></div>
  <script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-tickers.js">
  {
  "symbols": [
    {
      "title": "S&P 500",
      "proName": "INDEX:SPX"
    },
    {
      "title": "Nasdaq 100",
      "proName": "INDEX:IUXX"
    },
    {
      "title": "EUR/USD",
      "proName": "FX_IDC:EURUSD"
    },
    {
      "title": "BTC/USD",
      "proName": "BITFINEX:BTCUSD"
    },
    {
      "title": "ETH/USD",
      "proName": "BITFINEX:ETHUSD"
    },
    {
      "description": "Apple",
      "proName": "NASDAQ:AAPL"
    },
    {
      "description": "Berkshire",
      "proName": "NYSE:BRK.A"
    },
    {
      "description": "Microsoft",
      "proName": "NASDAQ:MSFT"
    },
    {
      "description": "Google",
      "proName": "NASDAQ:GOOG"
    },
    {
      "description": "Tesla",
      "proName": "NASDAQ:TSLA"
    },
    {
      "description": "Amazon",
      "proName": "NASDAQ:AMZN"
    },
    {
      "description": "AUD/USD",
      "proName": "OANDA:AUDUSD"
    },
    {
      "description": "Sony",
      "proName": "NYSE:SNE"
    },
    {
      "description": "BHP",
      "proName": "BHP"
    },
    {
      "description": "Telstra",
      "proName": "TLS"
    }
  ],
  "locale": "en"
}
  </script>
</div>
</div>
</div>
<!-- TradingView Widget END -->
<div class="content">
  <p>Some text.</p>
</div>

CSS:

body {
  margin: 0;
}
.content {
  padding: 10px 20px;
}
.content p {
  font-family: sans-serif;
}

/******/

.ticker-container {
  width: 100%;
  overflow: hidden;
}

.ticker-canvas {
  width: calc((200px * 15) + 2px);
  /* 
  200px = minimum width of ticker item before widget script starts removing ticker codes
  15 = number of ticker codes
  2px = accounts for 1px external border
  */
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
  -webkit-animation-timing-function: linear;
  animation-timing-function: linear;
  -webkit-animation-name: ticker-canvas;
  animation-name: ticker-canvas;
  -webkit-animation-duration: 20s;
  animation-duration: 20s;
}
.ticker-canvas:hover {
  animation-play-state: paused
}

@-webkit-keyframes ticker-canvas {
  0% {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    visibility: visible;
  }
  100% {
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
  }
}

@keyframes ticker-canvas {
  0% {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    visibility: visible;
  }
  100% {
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
  }
}
.tradingview-widget-container {
  position: relative;
}
.tradingview-widget-container iframe {
    position: absolute;
    top: 0;
}
.tradingview-widget-container iframe:nth-of-type(2) {
  left: 100%;
}

JS:

$( document ).ready(function() {
  $( ".tradingview-widget-container iframe" ).clone().appendTo( ".tradingview-widget-container" );
});
epsilon42
  • 1,863
  • 13
  • 26
  • Spot on, works perfectly. – DanielSon Jul 26 '18 at 03:26
  • As a final question, do you know how I can adjust the .tv-ticker-item-change__body {font-size: } value? It seems like it's generated in tradingview and is not able for me to adjust – DanielSon Jul 26 '18 at 03:48
  • This is difficult to do due to Same-origin policy. The browser won't allow you manipulate anything within the `iframe` DOM unless the `iframe` source happens to be on the same domain as the page loading the `iframe`. The [Wikipedia article](https://en.wikipedia.org/wiki/Same-origin_policy) for Same-origin policy lists some possible exceptions to this but I haven't had experience with any of the options described. – epsilon42 Jul 26 '18 at 15:45
  • 1
    You can style the `iframe` itself as a whole, e.g. applying transforms and CSS filters to it has potential to make it suit the styling on your site a bit more. Here's an OTT example: https://codepen.io/epsilon42/pen/GBvQrq – epsilon42 Jul 26 '18 at 16:41
  • Thanks again for saving me! – DanielSon Jul 27 '18 at 05:58
6

You have a little bit wrong question and because of this wrong answers. The correct question schould be like follows:

  • How can I scroll a tradingview ticker widget?

I ... wanted to know if there is a way to:

  1. make the ticker bar scroll (iFrame scrolling=yes)
  2. re-size the widget.

Yes, the ticker bar scroll and re-size of the widget are possible, but we do not need for this iFrame scrolling=yes.

Instead of this we wrap this iframe with a div and resize scroll this div element. This information you could find in other words as a hint on the tradingview ticker widget site:

The description says that I can display up to 15 symbols using the Ticker Widget. Why do I see only 5?

The Ticker widget uses the Autosize parameter by default. This means that it accepts the width of the parent element. Our demo page is wide enough to show only 5 symbols. You should make the parent element wider to see all the symbols.

Code example

function resizeWidget()
{
    var containerTradingview = document.querySelector('#container-tradingview');
    containerTradingview.style.maxWidth = '630px';
}
<center>
<div id="container-tradingview" style="max-width:420px;height:90px;overflow-x:auto;overflow-y:hidden">  
<div style="width:2100px">
<!-- TradingView Widget BEGIN -->
<div class="tradingview-widget-container">
    <div class="tradingview-widget-container__widget"></div>
    <div class="tradingview-widget-copyright">
        <a href="https://www.tradingview.com" rel="noopener" target="_blank">
            <span class="blue-text">Quotes</span>
        </a> by TradingView
    </div>
    <script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-tickers.js" async>
    {
        "symbols":
        [
            {"title": "S&P 500", "proName": "INDEX:SPX"},
            {"title": "Nasdaq 100", "proName": "INDEX:IUXX"},
            {"title": "EUR/USD", "proName": "FX_IDC:EURUSD"},
            {"title": "BTC/USD", "proName": "BITFINEX:BTCUSD"},
            {"title": "ETH/USD", "proName": "BITFINEX:ETHUSD"},
            {"title": "Groupon Inc.", "proName": "NASDAQ:GRPN"},
            {"title": "Walmart Inc.", "proName": "NYSE:WMT"},
            {"title": "Amazon Inc.", "proName": "NASDAQ:AMZN"},
            {"title": "Yelp Inc.", "proName": "NYSE:YELP"},
            {"title": "eBay Inc", "proName": "NASDAQ:EBAY"}
        ],
        "locale": "en"
    }
    </script>
</div>
<!-- TradingView Widget END -->
</div></div>
<br>
<input type="button" value="Resize widget" onclick="resizeWidget()">
</center>

You can not execute this widget on SO because iframe from this snippet is in sandbox.

Please see this example on codepen.io.

Bharata
  • 13,509
  • 6
  • 36
  • 50
  • Yeah the guy that was awarded the bounty understood what I said, and executed code that solved my issue. He didn't require clarification, he understood. Your code however doesn't work in Codepen, and would not have been awarded anyway. – DanielSon Jul 26 '18 at 13:44
  • @McLeodx, my code works in Codepen, but does not work here because iframe from this snippet is in sandbox. – Bharata Jul 26 '18 at 13:55
  • https://imgur.com/a/wAjx98V your code does not work on Codepen, unless you're trying to only display 3 tickers out of 15 and you don't want it to scroll – DanielSon Jul 26 '18 at 14:38
  • @McLeodx, please upload your image to SO here: https://stackoverflow.com/questions/ask and then give me a link. I have **only** 10 elements and not 15. My ticker has the horisontal scroll bar and I checked it on Codepen - it works for me. – Bharata Jul 26 '18 at 14:47
4

As far as i know, you can't modify or adjust the content of an iframe (there's a workaround to this but it's a bit tricky); it's due to same-origin policy. However you can still interact with the tag itself since it should be the same origin/domain as your own code. I've tested the code and noticed the iframe is added dynamically from tradingview's javascript. What you could do is waiting for it to be loaded and then adding the css property overflow=scroll.

<script type="text/javascript"> setTimeout(function() {document.querySelector("iframe").style.overflow="scroll";}, 500); </script>

The problem is that it wont even work because tradingview's code is automatically adding/removing trading pairs based on window's width, meaning the iframe or the container of the pairs won't ever be overflowed. Try to zoom-in/zoom-out while looking at the pairs html code and you can see that's what's happening.

Your last solution is to take another look at tradingview's api to make sure they haven't implemented any way to scroll the trading pairs container yet. If so, you should contact their technical support and explain your problem to them.

If you really want to tweak the iframe's content and thus get rid of the same-origin policy limitations, you can use the server side solution i mentioned earlier https://stackoverflow.com/a/35053713/8538711. It's writen using php but the solution probably applies to other server-side languages.

  • Sure I saw that the width of the page determines how many ticker boxes are displayed. I'm trying to have around 10 - 15 total tickers displaying, with 5 or 6 on the page at any one time, and it horizontally scrolling. After reading your CSS overflow=scroll idea, is there no way to adjust the iFrame param for scrolling from no to yes? – DanielSon Jul 19 '18 at 14:42
  • You could try to add within the timeout : `document.querySelector("iframe").setAttribute("scrolling", "yes");` But again, since tickers are automatically added/removed to fit the document's width, it shouldn't display any scrollbar because the iframe shouldn't ever be overflowed by its content. We could probably work around that but we'd have to butcher the javascript provided with the iframe. It'd clearly be way easier if tradingview themselves could implement a way to scroll the tickers container. – BaguetteSeeker Jul 19 '18 at 15:27
  • When I add more than 5 tickers to the widget (10 for example) I can scroll the page to the right by a whole other page width with nothing apart from whitespace and the tickers in position 6 - 10. Does this mean that it does overflow? – DanielSon Jul 19 '18 at 15:43
  • If there's a scrollbar displayed that allows you to look at all you tickers then yes, it does overflow. – BaguetteSeeker Jul 19 '18 at 15:51
  • Are you able to adjust your answer so that it provides a clear suggestion. Then I'll try that and will award bounty if it works. – DanielSon Jul 23 '18 at 06:26
  • The answer it at least as clear as the question. You provided very little details and didn't even mentioned the fact that the ticker widget is autosizing, which is specified on its very frontpage. Knowing this would have helped me to provide a much clearer and concise answer. You asked how to resize and scroll the widget which is contained in an external iframe with cross-origin limitations, so i explained how to get rid of these limitations. I also provided the javascript code to make iframe scrollable once the server side solution is applied, just as you asked. – BaguetteSeeker Jul 24 '18 at 22:44
  • Thank you for your efforts, and I'm sad to see that you are so upset. The person that was awarded the bounty received the same instructions that you did, and they were able to perfectly solve the problem - so I think that maybe the problem isn't with my question. – DanielSon Jul 26 '18 at 13:47
  • I'm not upset, just annoyed to waste my time with completly unclear and missleading questions that could have been answered properly in two lines. The question is very vague, contains almost no details and show very little reserach efforts since you didn't even include in it the basic functionning of the widget, which is specified in the short doc you linked us. Which tells us you haven't even bothered to read it entierly if not at all. My answer is not the only one pointing out the low quality of your question, meaning i'm probably not the one who's wrong here. – BaguetteSeeker Jul 26 '18 at 16:42
  • Also, don't act so cocky when you face criticism, especially in the area of learning where people try to improve and help each other; which is exactly what a place like stack overflow is about. Sorry if you found yesterday's comment to be unfriendly. Because what it says is actually just : "I answered your question, not your problem. If your question doesn't explain your problem clearly enough (which if often the case when you get an answer that seems off topic while still mentioning elements of the question) then try to fix it, add details to it. Basically just try to clarify it." – BaguetteSeeker Jul 26 '18 at 16:44
  • And I understand what you said, and agree that stackoverflow is for learning. But the fact remains that someone else easily completed this task. If you couldn't I don't think it's fair to blame my question. If you answered correctly you would have more than 66 points right now. – DanielSon Jul 26 '18 at 18:35
4

@McLeodx, afaik i don't thing you have control over iframe, instead you can do something which i have done, please have a look at the below working example or here(codepen link), hope it helps :)

.container-outer {
  max-width: 960px;
  /* update the width of the display contaier as per your requirement */
}
.container-width {
  width: 3000px;
  /* Total width of the whole iframe, based on the number of tickers displaying */
}
<!--  -->

.container-outer {
  margin: 0 auto;
  max-width: 960px;
  position: relative;
  box-shadow: inset 0 43px 0 0 #eee;
  border-bottom: 1px solid #ccc;
  height: 71px;
  overflow: hidden;
}
.container-outer:before,
.container-outer:after {
  top: 0;
  width: 1px;
  height: 100%;
  content: '';
  position: absolute;
}
.container-outer:before {
  border-left: 1px solid #ccc;
}
.container-outer:after {
  right: 0;
  border-right: 1px solid #ccc;
}
.container-inner {
  overflow-x: auto;
  overflow-y: hidden;
  height: 100px;
}

.shadow-left:before,
.shadow-right:after {
  width: 20px;
}

.shadow-left:before {
  background: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.15)), to(transparent));
  background: linear-gradient(to right, rgba(0, 0, 0, 0.15) 0%, transparent 100%);
}

.shadow-right:after {
  background: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0.15)), to(transparent));
  background: linear-gradient(to left, rgba(0, 0, 0, 0.15) 0%, transparent 100%);
  right: 0;
}
<div class="container-outer">
  <div class="container-inner">
    <div class="container-width">
      <!-- TradingView Widget BEGIN -->
      <div class="tradingview-widget-container">
        <div class="tradingview-widget-container__widget"></div>
        <div class="tradingview-widget-copyright">
          <a href="https://www.tradingview.com" rel="noopener" target="_blank">
            <span class="blue-text">Quotes</span>
          </a> by TradingView
        </div>
        <script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-tickers.js" async>
          {
            "symbols": [
              {
                "title": "S&P 500",
                "proName": "INDEX:SPX"
              },
              {
                "title": "Nasdaq 100",
                "proName": "INDEX:IUXX"
              },
              {
                "title": "EUR/USD",
                "proName": "FX_IDC:EURUSD"
              },
              {
                "title": "BTC/USD",
                "proName": "BITFINEX:BTCUSD"
              },
              {
                "title": "ETH/USD",
                "proName": "BITFINEX:ETHUSD"
              },
              {
                "title": "S&P 500",
                "proName": "INDEX:SPX"
              },
              {
                "title": "Nasdaq 100",
                "proName": "INDEX:IUXX"
              },
              {
                "title": "EUR/USD",
                "proName": "FX_IDC:EURUSD"
              },
              {
                "title": "BTC/USD",
                "proName": "BITFINEX:BTCUSD"
              },
              {
                "title": "ETH/USD",
                "proName": "BITFINEX:ETHUSD"
              },
              {
                "title": "S&P 500",
                "proName": "INDEX:SPX"
              },
              {
                "title": "Nasdaq 100",
                "proName": "INDEX:IUXX"
              },
              {
                "title": "EUR/USD",
                "proName": "FX_IDC:EURUSD"
              },
              {
                "title": "BTC/USD",
                "proName": "BITFINEX:BTCUSD"
              },
              {
                "title": "ETH/USD",
                "proName": "BITFINEX:ETHUSD"
              }
            ],
              "locale": "en"
          }
        </script>
      </div>
      <!-- TradingView Widget END -->
    </div>
  </div>
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
  // Scroll Shadow
  $(document).ready(function() {
    $(".container-inner").on("scroll", function () {
      var cur = $(this).scrollLeft();
      if (cur == 0) {
        $('.container-outer').addClass('shadow-right').removeClass('shadow-left');
      }
      else {
        var max = $(this)[0].scrollWidth - $(this).parent().width();
        if (cur == max) {
          $('.container-outer').addClass('shadow-left').removeClass('shadow-right');
        } else {
          $('.container-outer').addClass('shadow-right shadow-left');
        }
      }
    });
    $(".container-inner").trigger("scroll");
  });
</script>
Girisha C
  • 1,922
  • 1
  • 12
  • 20
  • Not sure why `Run code snippet` is not showing the results properly :(, you can check the codepen link, which is working fine - https://codepen.io/girish/pen/Epmrba – Girisha C Jul 24 '18 at 13:38
  • Girish this looks good in codepen - is there any way to make it automatically scroll in a loop like something on Bloomberg.com? If you can autoscroll I will make this answer as correct and provide the bounty – DanielSon Jul 24 '18 at 17:38
  • @McLeodx, please check this link for widget with marquee effect - https://codepen.io/girish/pen/mjwBMW – Girisha C Jul 25 '18 at 07:46
  • its kind of working except that a) It's rotating in the opposite direction to your example, b) it's rotating much slower, c) the first 6 show and then when it starts rotating then whitespace follows instead of it being a loop. After the 6 have all moved out of the space, the bar is white for a second and then all 6 of the first one appear again and restart. This is with 15 that should be looping. – DanielSon Jul 25 '18 at 12:43
  • I've sped up the rotation speed but issues a) and c) still stand currently – DanielSon Jul 25 '18 at 13:01
  • can u share the link where u have updated it? or give me the actual ticker values to pass. – Girisha C Jul 25 '18 at 14:41
  • also if you look at the css in codepen, i have added few comments based on your requirement you need to update the value. – Girisha C Jul 25 '18 at 15:16
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/176736/discussion-between-girish-and-mcleodx). – Girisha C Jul 25 '18 at 15:42
  • Sure, just messaged there – DanielSon Jul 25 '18 at 16:16