Text not fully redrawing when I toggle between templates - javascript

On my AngularJS app I have a view that allows me to toggle between type of insurance cover and it works fine. However on iPhone in particular (Chrome & Safari), the text kind of scrambles when I toggle between the prices. To be very clear about it, it's only the top few pixels and those pixels generally belong to the price toggled away from, so it's like the page isn't properly redrawing it. This issue then goes away if I do anything in the Dev tools. Any help is appreciated here.
EDIT: This appears to only happen when I select an option that updates the value displayed, not when it switched to a different piece of template.
Here's a screenshot
And a slightly stripped down version of the template in question:
<div class="row quote-tab-container">
<div class="col">
<div class="quote__tab">
<button ng-click="selectedCoverType = 'Comp'; setCoverDetails()" class="quote__tab__button">
Comprehensive
<div class="active-selection" ng-show="selectedCoverType === 'Comp'"></div>
</button>
<button ng-click="selectedCoverType = 'Tpft'; setCoverDetails()" class="quote__tab__button">
Third Party,<br />Fire & Theft
<div class="active-selection-tpft" ng-show="selectedCoverType === 'Tpft'"></div>
</button>
</div>
</div>
</div>
<div class="quote-details row">
<div class="col">
<div class="answer--radio">
<input ng-click="paymentType = 'CC'" type="radio" ng-checked="paymentType == 'CC'" id="singlePayment" name="payment-type">
<label for="singlePayment">Single Payment</label>
</div>
<div class="answer--radio answer--radio--right">
<input ng-click="paymentType = 'DD'" type="radio" ng-checked="paymentType == 'DD'" id="monthlyPayments" name="payment-type">
<label for="monthlyPayments">Monthly Payments</label>
</div>
<section class="selected-product answer--checkbox" ng-show="paymentType == 'CC'">
<div class="your-online-price">
Your online price is
</div>
<div class="selected-product__price">
{{totalPremium | signedCurrencyFilter}}
</div>
<div class="selected-product__includes">
Price includes online discount of {{onlineDiscount | signedCurrencyFilter}}
</div>
</section>
<section class="selected-product answer--checkbox" ng-show="paymentType == 'DD'">
<div class="your-online-price">
Your online price is
</div>
<div class="selected-product__price">
{{instalmentAmount | signedCurrencyFilter}}
</div>
<div class="selected-product__includes">
Price includes online discount of {{onlineDiscount | signedCurrencyFilter}}
</div>
</section>
</div>
</div>

So because the browser would correct this glitch whenever the screen resized or had to redraw I had to force a redraw any time these options were selected. The best way to do this seemed to be to clone the element and replace the original with the clone in order to force a redraw, this was enclosed in a timeout in order to send this to the end of the execution queue.
This answer helped with this: https://stackoverflow.com/a/8840703/1999035
var n = document.createTextNode(' ');
var opacity = element.style.opacity;
element.appendChild(n);
element.style.opacity = '0.5';
setTimeout(function(){
element.style.display = opacity;
n.parentNode.removeChild(n);
}, 20);
My edit of the proposed solution is to use the opacity property rather than display, because the display change causes a jitter/glitch/flash that looks really bad.Opacity just causes a slight fade.

Related

How to show element only if other element contains something using jQuery?

My guess is what I want to achieve should be easy, but due to my lack of knowledge of front-end development, I cannot manage to solve issue. Have a page that works with AJAX-filters that users can select. Filters that are currently applied show up within <div> with id=current-filters.
HTML looks like this:
<div id="current-filters-box">
<div style="margin-bottom: 15px">
<strong>Current filters:</strong>
<div id="current-filters">
<!-- here every single applied filter is displayed -->
</div>
</div>
</div>
Need to hide the the entire DIV current-filters-box in case no filter is applied.
The page uses a Javascript file, bundle.js which is massive, but contains the following line:
s=document.getElementById("current-filters")
Therefore tried the following if-statement to hide the DIV:
if(s.length<1)$('#current-filters-box').hide()
and
if(s=0)$('#current-filters-box').hide()
But this does not seem to have any effect. Can someone tell, what I did wrong?
Demo of page can be found here
EDIT: this is what the HTML looks like when filters are applied:
<div id="current-filters-box">
<div style="margin-bottom: 15px">
<strong>Current filters:</strong>
<div id="current-filters">
<div class="badge-search-public">
<strong>Humanities & Languages</strong> <span class="x" data-property="disciplines" data-value="4" onclick="filter.removeFilter(this)">×</span>
</div>
<div class="badge-search-public">
<strong>January</strong> <span class="x" data-property="months" data-value="1" onclick="filter.removeFilter(this)">×</span>
</div>
</div>
</div>
Both of your conditions are incorrect or I would say they are not doing what you think they do.
s.length will always prints undefined so instead of s.length<1 you could use s.children.length
and the second one is not a condition rather it is an assignment
s==0 // condition
s=0 //assignment
the correct condition for your requirement would be
if(s.children.length<1){
I have assigned snippets for illustration.
Without filters
s = document.getElementById("current-filters")
console.log(s.children.length);
if (s.children.length < 1) {
$('#current-filters-box').hide(1000)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="current-filters-box">
filter box
<div style="margin-bottom: 15px">
<strong>Current filters:</strong>
<div id="current-filters">
<!-- here every single applied filter is displayed -->
</div>
</div>
</div>
Without filters
s = document.getElementById("current-filters")
console.log(s.children.length);
if (s.children.length < 1) {
$('#current-filters-box').hide(1000)
}
<div id="current-filters-box">
<div style="margin-bottom: 15px">
<strong>Current filters:</strong>
<div id="current-filters">
<div class="badge-search-public">
<strong>Humanities & Languages</strong> <span class="x" data-property="disciplines" data-value="4" onclick="filter.removeFilter(this)">×</span>
</div>
<div class="badge-search-public">
<strong>January</strong> <span class="x" data-property="months" data-value="1" onclick="filter.removeFilter(this)">×</span>
</div>
</div>
</div>
Try this .
if( $('#current-filters').is(':empty') ) {
$('#current-filters-box').hide()// or $('#current-filters-box').css("display","none")
}
You are performing an assignment, try..
if (s.children.length)
Using vanilla JavaScript, you can check if the current-filters div is empty or not and toggle the parent div current-filters-box like this:
s= document.getElementById("current-filters");
t= document.getElementById("current-filters-box");
if(s.children.length<1) {
t.style.display = 'none';
// t.style.visibility= 'hidden'; <<-- use this if you want the div to be hidden but maintain space
}
else {
t.style.display = 'block';
// t.style.visibility= 'visible'; <<-- use this if you used visibility in the if statement above
}
You can achieve this by adding your own variable which counts or maintains your applied filters, e.g.
var applied_filter_count = 0;
at every time filter is applied
applied_filter_count++;
if(applied_filter_count) {
$('#current-filters-box').show()
}
and at every time filter is removed
applied_filter_count--;
if(!applied_filter_count) {
$('#current-filters-box').hide()
}
and by default current-filters-box should be display:none

Slider animation handle with JQuery, hover element issue using promises

I have problem with a slider. It works correctly without one, strange for me, situation. When I mouseover fast from one dot to another, it will not wait until previous animation ends and two texts overlap. Can somebody older and wiser help me?
HTML structure of project:
<section class="product-section">
<div class="vertical-text vertical-text-custom-5">
Pluginy
</div>
<div class="carrousel-image-container-1 product-release-management">
<i class="image-carrousel-1"></i>
</div>
<div class="carrousel-image-container-2 product-SLA">
<i class="image-carrousel-2"></i>
</div>
<div class="carrousel-image-container-3 product-test-management">
<i class="image-carrousel-3"></i>
</div>
<div class="col-custom-5">
<div class="col-custom-7 text-size-xl">
<div class="text-container-17">
<div class="product product-release-management">
<span class="text-color-6 text-weight-thin">Rivet</span> <br>
<span class="text-color-5 text-weight-bold">Release Management</span> <br>
<span class="text-color-3 text-weight-bold">plugin</span>
</div>
<div class="product product-SLA">
<span class="text-color-6 text-weight-thin">Rivet</span> <br>
<span class="text-color-5 text-weight-bold">SLA</span> <br>
<span class="text-color-3 text-weight-bold">plugin</span>
</div>
<div class="product product-test-management">
<span class="text-color-6 text-weight-thin">Rivet</span> <br>
<span class="text-color-5 text-weight-bold">Test Management</span> <br>
<span class="text-color-3 text-weight-bold">plugin</span>
</div>
</div>
<div id="carrousel-dots-contener" class="carrousel-dots text-color-5">
<div class="dot-container" data-carrousel-dot='dot-1'>
<div class="dot-border">
<div class="dot dot-custom-2">●</div>
</div>
</div>
<!--
-->
<div class="dot-container" data-carrousel-dot='dot-2'>
<div class="dot-border">
<div class="dot dot-custom-2">●</div>
</div>
</div>
<!--
-->
<div class="dot-container" data-carrousel-dot='dot-3'>
<div class="dot-border">
<div class="dot dot-custom-2">●</div>
</div>
</div>
</div>
</div>
</div>
REST OF CODE HERE
These are the main issues:
The promise() call works fine when you are sure you don't need to interrupt the animation, but as soon as you have mouse events that need immediate action (like hideAll), this promise will become a problem: it will still resolve, but at an inconvenient moment. In fact, as soon as you do another animation like hideAll, you want to cancel the execution of the code that follows the resolved promise. So... add a condition before proceeding with fadeIn() to see that the product selection is still relevant.
runInterval calls cyclicChange immediately, which is great when the page loads, but which is a bit annoying when moving the mouse over one dot to the next: as the mouse may exit the area, runInterval gets called and makes the selection jump to potentially another dot, which makes it kinda jumpy. It is better to remove this immediate call to cyclicChange and then to add some code to show the first product when start runs.
To avoid unwanted queuing of animations, you could call stop(true) before doing fadeOut().
I applied these changes to your JavaScript code, where I also made some other improvements, unrelated to the problem:
var carrousel = (function() {
var interval = null,
products,
current = -1;
products = [
'.product-release-management',
'.product-SLA',
'.product-test-management'
];
function showProduct(id) {
// Avoid unnecessary work
if (id == current) return; // nothing to do;
// In other cases: hide first
hideAll();
current = id;
$('.product').promise().done(function() {
// Make sure selection is still like at the start of showProduct execution
if (current === id) $(products[current]).fadeIn(500);
});
$("div[data-carrousel-dot='dot-" + (current + 1) + "']").addClass('dot-active');
}
function hideAll() {
// 1. easier selector for selecting all product classes
// 2. stop any ongoing animation
$(products.join(",")).stop(true, true).fadeOut(500);
$("div[data-carrousel-dot").removeClass('dot-active');
}
function cyclicChange() {
if ( isNaN(interval) ) return; // timer is not active
showProduct((current + 1) % products.length); // easier way to roundtrip
}
function runInterval(){
interval = setInterval(cyclicChange, 3000);
}
function mouseOverDotHandler() {
$('.dot-container').hover(
function() {
// Easier way to get number
showProduct($(this).index());
}
);
$('#carrousel-dots-contener').hover(
function(){
clearInterval(interval);
interval = null; // use variable for indicating the pause
},
runInterval
);
}
return {
start: function() {
showProduct(0);
runInterval();
mouseOverDotHandler();
}
}
})();
$(document).ready(function(){
carrousel.start();
});
See it run on jsbin.com.

Making a switching news feed for a web page

For a project i'm working on the users that are logged in with enough priveledge to post a new news item are able to see a button to add news items. I would like to show these news item with 'switching styles' (for the lack of a better word). I'm pulling the data from a database where the user submits it through a form on a seperate page. Then i'm requesting all of the news items back on the home page where it lists them as a 'news feed'. The feed fetches like a charm and can be seen here : http://prntscr.com/et39yp
I would like to make the second, fourth, sixth, etc have the first-image or first-video list on the left, like so : http://prntscr.com/et3akw
Is there an easy way of doing this?
#{
var db = Database.Open("Default");
var fetchRows = "SELECT * FROM Articles";
db.Execute(fetchRows);
var articles = db.Query("SELECT articleTitle, articleText, articleVideoUrl, articleImage FROM Articles ORDER BY id DESC");
var articleTitle = db.Query("SELECT articleTitle FROM Articles");
string lorem = "";
}
<div class="Articles">
<h2>Nieuws Feed</h2>
#foreach (var title in articles)
{
<div class="article">
#{
string text = title.articleText;
string firstLetters = new string(text.Take(50).ToArray());
<div class="col s6">
<h3>#title.articleTitle</h3>
<p>#firstLetters</p>
Lees meer...
</div>
<div class="col s6">
#{
if (title.articleVideoUrl != lorem)
{
//Iframe for youtube feed here
}
else if (title.articleVideoUrl == lorem && title.articleImage != "")
{
<div class="result">
<img src="#title.articleImage" alt="image"/>
</div>
}
}
</div>
}
</div>
}
</div>
Now the switching news article thing is something i would be able to work out, the thing i'm struggling with would be the following. The user is able to edit / remove news items. So i cant keep track of an index value or anything similar since it would be invalid should the user remove an item from the middle of the feed. My first guess would be to use the .toggleclass of javascript and that would probably work with originially loading the items but if the user would remove an item it wouldn't show them the right way after. Any help would be welcome.
It shouldn't matter that you are adding the items individually, the nth-child(odd|even) should still work.
You can see it working here: http://jsfiddle.net/Chairman_Mau/uap93rtL/4/ - notice when you click the move up/move down buttons the style changes automatically.
HTML
<div class="articles">
<h1>header</h1>
<div class="article">
paragraph
</div>
<div class="article">
paragraph
</div>
<div class="article">
paragraph
</div>
<div class="article">
paragraph
</div>
<div class="article movethis">
paragraph - move this one
</div>
<div class="article">
paragraph
</div>
<input type="button" value="add article" class="addarticle"/>
<input type="button" value="move up" class="moveup"/>
<input type="button" value="move down" class="movedown"/>
</div>
Javascript
$(".addarticle").click(function () {
$(".articles").append('<div class="article">added</div>');
});
$(".moveup").click(function(){
var prev = $(".movethis").prev('.article');
$(".movethis").detach().insertBefore(prev);
});
$(".movedown").click(function(){
var next = $(".movethis").next('.article');
$(".movethis").detach().insertAfter(next);
});
CSS
.articles .article:nth-of-type(even)
{
color: Green;
}
.articles .article:nth-of-type(odd)
{
color: Red;
}

AngularJs ng-show for when an item in a list is true in one line

I have a condition where basically what I want to do is if there is a bool set to true I want to toggle. But the bool is attached to items in a list. Take a look:
<div ng-repeat="step in progress.steps">
<div ng-if="step.criticalError">
</div>
</div>
Simple enough.
Now the problem!
Take a step backward to the containing divs. I want to handle a scenario like this..Have 3 divs. Only 2 will show at a time. The factor that determines that is the criticalError. It is an all or nothing, so if one trips as a critical error then all the steps show on top; otherwise they will all show below if there is no critical. So like this.
<div ng-show="containsCriticalError"></div>
<div>Always shows.</div>
<div ng-show="!containsCriticalError"></div>
Or would you have to iterate through the list, is it possible to stop an ng-repeat once a condition is met?
What about this?
<div ng-show="!containsCriticalError">Always shows.</div>
<div>
<div ng-repeat="step in progress.steps">
<div ng-if="step.criticalError">
</div>
</div>
</div>
<div ng-show="containsCriticalError">Always shows.</div>
Or just move the div with CSS?
Might be a bit funky, but it works
<div ng-repeat="step in progress.steps"
ng-init="show = !step.criticalError && ($$prevSibling || {show: true}).show">
<div ng-if="show">
</div>
</div>
EDIT:
I misread the question. The above approach displays only the steps above the first criticalError.
Here's what I think the OP is requesting:
<div ng-if="!show.v">Always shows...</div>
<div ng-init="show = {v: false}">
<div ng-repeat="step in steps"
ng-init="show.v = step.criticalError || show.v">
</div>
</div>
<div ng-if="show.v">Always shows...</div>

Take div and insertAfter when div loads

Building a site that gives play by play info for a game and want to insert a div after a specific div appears.
<div id="pbp-no-drive-0-0" class="no-drive">
<span></span>
</div>
<div id="pbp-no-drive-0-1" class="no-drive">
<span></span>
</div>
<div id="pbp-0-0" class="all-plays">
<div class="drivesum></div>
<div id="pbp-in-drive-0-3" class="play-in-drive">
</div>
<div id="pbp-no-drive-0-25" class="no-drive">
<span></span>
</div>
<div id="pbp-0-1" class="all-plays">
<div class="drivesum"></div>
</div>
The "no-drive" divs will appear first, the "all-plays" div appears after a drive has started. I'm attempting to insert the "no-drive" divs after "drivesum" divs if they are already not there. There are multiple "all-plays" and "no-drives". It is for american football and the "no-drives" represent special teams kicking off.
What would be the best way to handle this?
You can write up a conditional statement. If you are not sure when this would be appended, then you can have a timer in place.
var timer;
timer = setInterval(function() {
if( !$('.all-plays').find('.no-drive').length) {
$('.no-drive').insertAfter('.drivesum');
clearInterval(timer);
}
}, 100);

Categories

Resources