Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

Rodrigo last won the day on March 17 2019

Rodrigo had the most liked content!

Rodrigo

Moderators
  • Posts

    1,768
  • Joined

  • Last visited

  • Days Won

    158

Everything posted by Rodrigo

  1. Hi, That message means that IT IS working, if you check the code for the fallback array, that means the files loaded in the nope value, you'll see that the red background, the text and the animation of the pink element are in those files: JS var div1 = $("div#div1"), div2 = $("div#div2"); div1.append('<p>This Browser DOES NOT SUPPORT CSS 3D Transforms. BUMMER :_(</p>'); TweenMax.to(div2, 2, {left:200, repeat:-1, yoyo:true}); CSS #div1{ height:50px; width:500px; line-height:50px; background:#F00; } #div2{ height:100px; width:100px; background:#f0f; position:relative; margin:50px; } And if you check the same page using firefox, chrome, safari or opera you'll see that the div element has a blue background, white letters and the pink element is making a 3D transform tween: JS var div1 = $("div#div1"), div2 = $("div#div2"); div1.append('<p>This Browser DOES SUPPORT CSS 3D Transforms. HURRAY </p>'); TweenMax.to(div2, 2, {rotationY:360, rotationX:45, repeat:-1, yoyo:true}); CSS #div1{ height:50px; width:500px; line-height:50px; background:#00F; border-radius:10px; color:#fff; padding:0 10px; font-weight:bold; } #div2{ height:100px; width:100px; background:#f0f; position:relative; margin:50px; } Remember that since IE9- doesn't support CSS3 3D transforms, yepnope is going to load the files you indicate if the modernizr test fails, and if you don't indicate any files, is not going to load anything. So keep in mind to always include the nope indication and point to some files in there otherwise you'll end up with a page without css and js. Hope this clarifies a little more. Cheers, Rodrigo.
  2. No problemo Phil, if more questions come up, keep asking. Cheers, Rodrigo.
  3. Hi and welcome to the forums. Mhhh it's a strange thing since both modernizr and YepNope work with IE6+ and as far as I know even with devices browsers. Check if you're pointing to the right files and/or paths in the modernizr.load function. Remember that the function takes key:value pairs and that the yep and nope test can take arrays as their values. Also see if you downloaded the correct file from modernizr. In order to get the files you have to do the following: Go to the download area in modernizr.com and select the tests you want to check By default YepNope is selected but anyway is not a bad idea to check. Then click on generate: And finally copy/paste the generated code into your text/html editor and save it. Then you do what's in my first post in this thread and it should work. Anyway i uploaded a live example that i have in my pc that is working with IE7+ (i don't test IE6 anymore but it should work). It has all the code and styles all you have to do is to update to the current version of GSAP since it's working with 1.8.0 Also it would help if you could set a live example to take a better look. Hope this helps, Cheers, Rodrigo.
  4. Hi, Yesterday I couldn't set an example of my idea, so here it is: http://jsfiddle.net/rhernando/k5gm4/ As you'll see i didn't use the code suggested by Paul Irish because on further experimenting you get the same result with setInterval, maybe someone with more experience in this could enlighten us a little more in order to know what's the best choice. I chosen setInterval only because is less code. Cheers, Rodrigo.
  5. Hi, It maybe a way to do it. If you check the demo with firebug or developer tools while you're scrolling up and down you'll see this (this captures are taken wit firebug 1.11.2 in Firefox 19). If you check there's two main elements that are going to change some of their css properties, wrapper and sp-scroll-bar, if you scroll down a little you'll see this: And if you scroll to the point where rotations begin to happen, you'll see this: As you can see you can track the change of either of those elements in order to get your tweens/timelines going, the only problem is that, as far as I can see and I maybe wrong about this, the best choice will be the scroll bar (class="sp-scroll-handle"). So all you have to do is relate the change in the top property of this element to the progress value of your tweens/timelines. The challenge is to find something in the plugin's code to do it and by taking a quick look to it I've found nothing, and if that's the case personally I'll spend my time creating my own solution without the plugin. The other way is to add some sort of Enter Frame event to constantly check the scroll handle's top property and use that to set the progress of the tweens/timeline. Honestly i would go with the second option and in that regard you can read this article to see how you can do it. Now in order to relate the scroll handle position and the progress of the tweens you can check this tutorial I made some time ago. And just like Carl said it would be nearly impossible to get the two plugins to work together in harmony. Hope this helps. Cheers, Rodrigo.
  6. Hi and welcome to the forums, Sure Greensock can handle any numeric value you throw at it so you can easily tween it. In this case you have to create an object and add a key:value pair, tween the value of that object and with an onUpdate callback pass that value as the timeline progress, something like this: var tl1 = new TimelineMax({paused:true}), tl1Prog = {a:0}; TweenMax.to(tl1Prog, 1, {a:1, onUpdate:updateFn}); function updateFn() { tl1.progress(tl1Prog.a); } Remember that the progress is between 0 and 1, and also keep in mind that you could add easing functions to the tween that changes the value. Hope this helps. Cheers, Rodrigo.
  7. Ha ha ha, see I told you there was a better way to do this Thanks Carl!!
  8. Hi, You're welcome. The fact is that when you create a timeline and use the convenience to method, the tween is added to the end of the timeline so there's no possible overwrite. You could try doing it with a negative value to generate an overlapping, therefore an overwrite should happen: var tl1 = new TimelineMax(); tl1.to(element, 1, {left:100}); tl1.to(element, 1, {left:50}, "-=1");//inserted 1 second before the timeline end For the same reason, as you said, when you create the tweens in the timeline, they keep the original values provided, if you modify your second code to this: var distanceX = 0; var distanceY = 0; var mytween = new TimelineMax(); function startAnimation() { var element=$("#element"); mytween.to(element, 2, {left:670}); mytween.to(element, 1, {rotation:90}); mytween.call(getXY); mytween.call(function() {alert("distanceX: " + distanceX + " distanceY: " + distanceY);}); mytween.to(element, 2, {top:distanceY}); mytween.to(element, 1, {rotation:0}); mytween.to(element, 2, {left:distanceX}); } function getXY() { distanceX=500; distanceY=300; } The element will tween to left:0 and top:0, because even with the values changing before the animation takes place, the tweens were created and putted in the timeline with the original values for distanceX and distanceY, those values never get to the timeline. In fact you could add this lines to the getXY function, after setting the new values to see it for yourself: var delTweens = tl1.getTweensOf(element); console.log(delTweens); If you go to the console and see the vars element of the last two tweens you'll see that the values are 0 for both. As for deleting the old tweens, if you don't the new tweens will be added to the end of the timeline, and since distanceX and distanceY are not defined the timeline will break and nothing will happen. Another possibility is to define the values of distanceX and distanceY as 0 in the variable creation, add labels to the timeline where the tweens are going to get the element to those values and then insert the new tweens right in those labels to force an overwrite. var distanceX = 0; var distanceY = 0; var mytween = new TimelineMax(); function startAnimation() { var element=$("#element"); mytween.to(element, 2, {left:670}); mytween.to(element, 1, {rotation:90}); mytween.call(getXY); mytween.call(function() {alert("distanceX: " + distanceX + " distanceY: " + distanceY);}); mytween.to(element, 2, {top:distanceY}, "label1"); mytween.to(element, 1, {rotation:0}); mytween.to(element, 2, {left:distanceX}, "label2"); } function getXY() { distanceX=500; distanceY=300; mytween.to(element, 2, {top:distanceY},"label1"); mytween.to(element, 2, {left:distanceX}, "label2"); } So like that when the function executes it'll add the new tweens in the same place where the old ones are but with the new values, forcing the overwrite and tweening the element to the new values. Cheers, Rodrigo.
  9. Hi, The main thing is that when your first function executes it adds all those tweens to the timeline, therefore when is time to change the top and left positions there are not deifned yet. What I can advice (and there's probably a better way) is to remove all the tweens added by the first function and then add new ones with the changed values: var distanceX = 0, distanceY = 0, tl1 = new TimelineMax(), element = $("div#element"), changeValues = false, btn1 = $("button#btn1"); function getxy() { distanceX = 300; distanceY = 100; var delTweens = tl1.getTweensOf(element); tl1.remove(delTweens); tl1.to(element, 1, {rotation:75}) tl1.to(element, 1, {top:distanceY}); tl1.to(element, 1, {left:distanceX}); } function startAnimation() { tl1.to(element, 1, {left:200}); tl1.to(element, 1, {top:200}); tl1.to(element, 1, {rotation:45}); tl1.call(getxy); tl1.to(element, 1, {rotation:0}); tl1.to(element, 1, {top:distanceY + 'px'}); tl1.to(element, 1, {left:distanceX}); } startAnimation(); So like that when you call the getxy function you all the tweens inside the timeline are removed and you add new ones, of course if you don't want this to happen unless the user want the original values of distanceX and distanceY changed, something like this: var distanceX = 0, distanceY = 0, tl1 = new TimelineMax(), element = $("div#element"), changeValues = false, btn1 = $("button#btn1"); function getxy() { if(changeValues) { distanceX = 300; distanceY = 100; var delTweens = tl1.getTweensOf(element); tl1.remove(delTweens); tl1.to(element, 1, {rotation:75}) tl1.to(element, 1, {top:distanceY}); tl1.to(element, 1, {left:distanceX}); } } function startAnimation() { tl1.to(element, 1, {left:200}); tl1.to(element, 1, {top:200}); tl1.to(element, 1, {rotation:45}); tl1.call(getxy); tl1.to(element, 1, {rotation:0}); tl1.to(element, 1, {top:distanceY + 'px'}); tl1.to(element, 1, {left:distanceX}); } btn1.click(function() { if(changeValues) { changeValues = false; } else { changeValues = true; } }) startAnimation(); So like that you can use the whether the original values or the new ones depending on a specific event that changes the the boolean to true, otherwise the timeline goes as planed. Check this http://jsfiddle.net/rhernando/tBZmA/1/ Maybe using the add method you can get something useful and less cumbersome but unfortunately that's all the time i have right now. Sorry for not coming up with something better Hope this helps, Cheers, Rodrigo.
  10. Hi, Considering the fact that is a footer what your tweening to I'm going to presume that is at the bottom or near the bottom of the page. If that's the case you can use the "max" method of the scrollTo plugin: TweenMax.to (window, 1, {scrollTo:{y:"max"}, onComplete:myFunction}); Like that the engine takes care of everything. You should consider that the scrollTo plugin will take the coordinates you're giving and put that point at the window's top position. To see it in action see this sample and click on the "scroll to marker" button and look that the purple div will end up at the top of the window, if you check the code you'll see that the marker position is obtained with the offset method. But still is an odd behavior, even if there's no space for scrolling the page or element the tween should play and complete, check this sample: http://websnap.cl/samples/scrollto.no.scrollbar.html Hope this helps, Cheers, Rodrigo.
  11. Hi, In fact greensock doesn't depend on any other library, now if you want to use greensock's JQuery animate plugin and JQuery selectors you'd need to load the library. Something like this: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset=utf-8" /> <title>Untitled Document</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.8.4/TweenLite.min.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.8.4/easing/EasePack.min.js"></script> <script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.8.4/plugins/CSSPlugin.min.js"></script> </head> <body> <script> </script> </body> </html> And then you can insert your script between the body tags. If you're using JQuery: $(document).ready(function(){ //CODE IN HERE }); If you're not using JQuery or other library, then you need to use pure javascript what brings the issue of crossbrowsing, which is not a small one, for that reason i will recommend you to use JQuery or other library (prototype is a good one to replace JQuery). Also using JQuery brings the benefit of a library that has been ultra tested and has lots of information, dedicated sites, tutorials, plugins, books, etc. to help you in learning how to use it. If you're interested in using JQuery i can recommend you the following sites: http://learn.jquery.com/ This is the official JQuery learning center, for the basic stuff to get started. http://www.jquery4u.com/ Blog dedicated completely to JQuery, lots of plugins and techniques, from beginner to advanced user. http://www.oscarotero.com/jquery/ Oscar Otero from Spain created a JQuery cheat sheet, this is not a way to "cheat" in JQuery because there's not such thing as that, but is q quick guide to the official JQuery api reference for different versions of the library. https://developer.mozilla.org/en-US/ Mozilla's developer network is always a good point for references, they have a lot of documents, tutorials and links to good resources. http://stackoverflow.com/questions/tagged/jquery And last but not least is stackoverflow, which is some kind of web development google, there's a lot of questions in there and also a lot of answers. Now if you're looking for a book to read I honestly wouldn't put that as a top priority, I've read books but didn't learn a lot from them but I'll recommend you the following: Javascript Step by Step For beginning with basic Javascript. Learning JQuery To learn the basics about JQuery. Well I hope this helps you a little. Cheers, Rodrigo.
  12. No problemo, glad to help. Carl, Jack question: I tried adding paused timelines inside an alive timeline and of course the parent timeline progresses but the nested ones were still paused, at the end the parent progress is 1 and the nested ones is 0. But if you un-pause the nested ones while the parent is playing, their progress starts at the parent progress and at the end all the progress values are 1. When nesting alive tweens/timelines inside a paused timeline the parent force the nested ones to be paused, why it doesn't works the other way?. Cheers, Rodrigo.
  13. Hi, Your problem is that your nested timelines are paused, so basically your master timeline is playing but the nested ones are still paused, change it to this: var master = new TimelineMax( {paused:true, onUpdate:masterUpdate}); var sec1 = new TimelineMax({onUpdate:sec1Update}); var sec2 = new TimelineMax({onUpdate:sec2Update}); master.add([sec1, sec2], "+=2", "stagger"); master.play(); And it should work. Also i set up a fiddle in case you want to see a working sample. http://jsfiddle.net/rhernando/KSdKe/ Hope this helps, Cheers, Rodrigo.
  14. Hi, It looks like you're asking for the parent's timeline labels and time, not the nested one, therefore the array is empty. Change your code to this: var tl1 = new TimelineMax(); var tl2 = new TimelineMax(); tl2.addLabel("tl2"); tl1.append(tl2); console.log(tl2.getLabelTime("tl2")); console.log(tl2.getLabelsArray()); I also took the liberty to update your fiddle so you can see it working: http://jsfiddle.net/fa7Wd/13/ Hope this helps, Cheers, Rodrigo.
  15. Hi, Does raphael allows the use of clipPath and defs?, sorry I'm ignorant about it and will like to know. What I've done is to create a common svg element: <?xml version="1.0"?> <svg style="position:relative;" id="paper1" width="300" height="50" viewPort="0 0 300 50" version="1.1" xmlns="http://www.w3.org/2000/svg"> <rect style="position:relative;" id="rect1" x="0" y="0" width="100" height="50"/> </svg> And then tween an object value and pass that through an onUpdate callback with JQuery: $(document).ready(function(){ var paper1 = $("#paper1").children().first(), elemWidth = {a:100}; TweenMax.to(elemWidth, 1, {a:300, onUpdate:updateFn}); function updateFn() { paper1.attr('width', elemWidth.a); } }); This works but is a little more code than an ideal situation and if you get more elements that would mean more coding and more callbacks. I hope someone with more SVG knowledge can take a hit to this. Also a live example (fiddle or codepen) would be very helpful. As you can see I'm not an SVG expert because is not my focus right now, but learning svg and canvas are on my to do list. Hope this helps, Cheers Rodrigo.
  16. Hi, I believe that is a Raphael element that you're trying to tween right?, if that's so you should use the raphael{} wrapper, something like this: TweenMax.to($('#mask-1').children().first(), 2, {raphael:{width:300}}); //or if you store the element in a var TweenMax.to(mc, 2, {raphael:{width:300}}); I'm not a raphael expert but at least that's what i recall from the api reference. Hope this helps. Cheers, Rodrigo.
  17. Hi, You know this was more simple than I thought. The thing is that in the first code you tried you were calling the add method every time the for loop executed so with that you're adding each tween at the end of the timeline. The second and third approaches were right on the spot regarding the for loop, but the problem was the creation of the timeline. The thing is that you created the tweens but by doing this: return new TimelineLite({paused: true, onComplete: callback, tweens: tweens}); no tween was included in your timeline, so the tweens were created and immediately executed that is why no stagger was happening. So what you should try is the last code I proposed: function getButtonsInAnimation(callback) { var i, spots, spot, tweens = [], timeLine = new TimelineLite({paused:true, onComplete: callback}); for(i in spots = shuffle(hotspots)) { spot = spots[i]; tweens.push(TweenLite.fromTo(spot, 0.3, {scale:0, alpha:0, left:200, top:100}, {scale:1, alpha:1, left:parseInt(spot.css('left')), top:parseInt(spot.css('top')), ease:Expo.easeOut} )); } return timeLine.add(tweens, 0, "stagger", 0.05) } Anyway I updated the fiddle. Hope this helps, Cheers, Rodrigo.
  18. Hi, I tested a few things and came up with the fact that not defining the position in which each tween is added to the timeline could be causing this issue, check this fiddle and play around with it, if you delete the '+=0' there's no staggering but if you keep that it will respect the stagger time you're giving it. I also added some callbacks into the tweens so you can also check how 'sequence' align works with and without a stagger time. tl.add([tween1, tween2, tween3], "+=2", "stagger", 0.5); If you don't declare "+=2" or maybe in this case "+=0" all the tweens are added at time 0 in the timeline, even if you declare an align string and stagger time. Maybe Carl or Jack could explain why this happens, I at least don't know. Cheers, Rodrigo.
  19. Hi, In your first approach try changing the align method (check the api) to "stagger", like this: function getButtonsInAnimation(callback) { var i, spots, spot, tween = new TimelineLite({paused: true, onComplete: callback}); for(i in spots = shuffle(hotspots)) { spot = spots[i]; tween.add(TweenLite.fromTo(spot, 0.3, {scale:0, alpha:0, left:290, top:168}, {scale:1, alpha:1, left:parseInt(spot.css('left')), top:parseInt(spot.css('top')), ease:Expo.easeOut} ), undefined, 'stagger', 0.05); } return tween; } For your last approach you could try multiplying the delay time by the i value in the for loop, something like this: function getButtonsInAnimation(callback) { var i, spots, spot, tweens = []; for(i in spots = shuffle(hotspots)) { spot = spots[i]; tweens.push(TweenLite.fromTo(spot, 0.3, {scale:0, alpha:0, left:200, top:100}, {scale:1, alpha:1, left:parseInt(spot.css('left')), top:parseInt(spot.css('top')), ease:Expo.easeOut, delay:0.05 * i} )); } return new TimelineLite({paused: true, onComplete: callback, tweens: tweens}); } Like that your tweens will be add in your timeline starting with the first value of i and then going up. And finally you could also try creating the array of tweens in the for loop and then add the array, like that your code will be more simple and you'll be tackling one thing first and then the other, so if you want to change something it will take less time doing so, like this: function getButtonsInAnimation(callback) { var i, spots, spot, tweens = [], timeLline = new TimelineLite; for(i in spots = shuffle(hotspots)) { spot = spots[i]; tweens.push(TweenLite.fromTo(spot, 0.3, {scale:0, alpha:0, left:200, top:100}, {scale:1, alpha:1, left:parseInt(spot.css('left')), top:parseInt(spot.css('top')), ease:Expo.easeOut} )); } return timeLine.add(tweens, "stagger", 0.05) } Hope this helps, Cheers, Rodrigo.
  20. Hi, It's just a syntax issue, you should declare it like this: $(topArea).animate({top: "-40px"}, 250, "easeInOutBounce"); And also you could declare it like this: $(topArea).animate({top: "-40px"}, {duration:250, easing:"easeInOutBounce"}); First put "ease", then if it's in/out/InOut and finally the easing function you want to use, unless you're using a native JQuery easing function like "linear" or "swing", in those cases there's no need to put "ease" at the beginning just the easing function's name as a string. Cheers, Rodrigo.
  21. Rodrigo

    GSJS Slider

    Hi Jeff, You mean using something like the JQuery UI slider (source) to control a timeline progress forward and backward?. If that's the case it's very simple, all you have to do is set the minimum and maximum values for the UI slider and associate the slider current value to a timeline progress, something like this: var scrollPos, progressValue; $(function() { $( "div#scrollMarker" ).slider({ range: "min", value: 0, min: 0, max: 1000, slide: function( event, ui ) { scrollPos = ui.value; progressTween(); } }); }); function progressTween() { progressValue = (scrollPos / 1000); TimeLine.progress(progressValue); } There are also a lot of slider codes out there in case you don't want to use JQuery's slider, just google. In terms of your second request I'm not quite sure what is what you want to achieve. Is a custom scrollbar using drag & drop animated with GSAP?, a menu that scrolls through the content of the div using the scrollTo plugin?. A little more info would be great. Cheers, Rodrigo.
  22. Hi, In order to get the properties being animated you could use this: var div1 = $("div#div1"), log = $("div#log"); TweenMax.to(div1, 2, {top:400, left:400, onUpdate:updateFn, onUpdateParams:['{self}']}); function updateFn(tween) { log.html('top: ' + tween.target.css('top') + ' // ' + 'left: ' + tween.target.css('left')); } You can see it working here: http://jsfiddle.net/rhernando/rLDTu/1/ Cheers, Rodrigo.
  23. Hi, I'm going to presume (and I'm maybe wrong) that your not familiar with Modernizr and YepNope. Those are two very cool libraries that could get the job done. Modernizr will test the visitor's browser in order to check if it support a specific feature (in this case css3 3D transforms) and YepNope will take that test result and load a specific set of files (it could also load just a single file) such as js and css files that will be loaded for that type of browser, like this there's no checking browser version or anything like that, you're just looking for if the browser supports that feature. In this case it would be like this: <script src="scripts/modernizr.3D.test.js"></script> <script src="scripts/TweenMax.min.js"></script> <script> Modernizr.load({ test: Modernizr.csstransforms3d, yep : ['scripts/css3d.js', 'scripts/yepnope/css3D.css'], nope: ['scripts/No.css3d.js','scripts/yepnope/No.css3D.css'] }); </script> So you just load the libraries (modernizr includes YepNope) and then you run the test. Once the test gets the results it takes the proper action. If the browser supports 3D transforms will load the files in the yep key:value pair, if it doesn't it will load the files in the nope key:value pair. The beauty of it it's that you can customize modernizr to include the test's you need, includes a series of classes in the html tag of the document and weights only 8.6 kb minified (you could go beyond it and gzip it and it would be even smaller) including YepNope. The document will look like this for a browser that supports 3D transforms (firefox 18): <html class=" js canvas no-touch csstransforms csstransforms3d svg" xmlns="http://www.w3.org/1999/xhtml" style=""> And like this if it doesnt (IE9): <html class=" js canvas no-touch csstransforms no-csstransforms3d svg" xmlns="http://www.w3.org/1999/xhtml"> Also modernizr can chek for and incredible set of stuffs allowing to create more concise code for each situation, so instead creating humongous css and js files filled with hacks you create separated files for each situation allowing you to deal with painfull degradation for IE browsers. In an aside note using YepNope independently allows you to create your own conditional logic to load your files both css and js. Take a look at them: http://modernizr.com/ http://yepnopejs.com/ Cheers, Rodrigo.
  24. Hi Jamie and all, Lately I've been dealing with some personal issues that hasn't allowed me to participate in the forums in a good fashion. You're right the code should be in a $(window).load() event to work as expected, for the same reason I've tested my codes only in firefox 17, and for that I ask everyone to forgive me, but I'm sleeping like crap, dealing with my issues and my business so my free time is small. I hope if isn't too much to ask for you to complete the examples, the example's code is complete in the html file so there's no javascript file to download, in fact the script, in a moment when i lost a chromosome, is between the head tags. Again sorry everyone for the inconveniences and thank you for your understanding. Like always....Cheers, Rodrigo.
  25. Hi, I've updated the examples with the code proposed by Jamie, but because the original sample had a menu and some animation that couldn't allow to see what happened on page refresh. Here are the updated links: http://websnap.cl/samples/scroll.to.sample.page.refresh.1.html http://websnap.cl/samples/scroll.to.sample.page.refresh.2.html The first one uses $(document).ready(function(){ TweenLite.set(window, {scrollTo:0}); //Rest of the code }); The second uses $(document).ready(function(){ $(window).bind('beforeunload', function () { window.scrollTo(0,0); }); //Rest of the code }); Cheers, Rodrigo. UPDATE: I moved the examples to my new blog, and created a slightly better sample for the page refresh here: http://codeaway.netii.net/sample.code/scroll.to/scroll.to.sample.page.refresh.html
×