Mithril: cannot m.redraw with m.render - mithril.js

I have an app where I want to control when to redraw the view.
I can make it work using m.mount and m.redraw:
var count = 0;
var Counter = {
view: function() {
return m('main', [
m('h1', ('Count: ' + count))
])
}
}
m.mount(document.body, Counter);
window.setInterval(function () {
count++;
m.redraw();
}, 200);
<html>
<body>
<script src="https://unpkg.com/mithril/mithril.js"></script>
<script src="index.js"></script>
</body>
</html>
But if i use m.render (because I don't need mithril to autoredraw) it no longer works:
var count = 0;
var Counter = {
view: function() {
return m('main', [
m('h1', ('Count: ' + count))
])
}
}
m.render(document.body, m(Counter)); // <-- The only changed line
window.setInterval(function () {
count++;
m.redraw();
}, 200);
<html>
<body>
<script src="https://unpkg.com/mithril/mithril.js"></script>
<script src="index.js"></script>
</body>
</html>
How can I make mithril redraw when using m.render instead of m.mount?

As stated here in the mithril docs:
Note that m.redraw only works if you used m.mount or m.route. If you rendered via m.render, you should use m.render to redraw.
var count = 0;
var Counter = {
view: function() {
return m('main', [
m('h1', ('Count: ' + count))
])
}
}
m.render(document.body, m(Counter));
window.setInterval(function () {
count++;
m.render(document.body, m(Counter)); // <-- Use m.render here, not m.redraw
}, 200);
<html>
<body>
<script src="https://unpkg.com/mithril/mithril.js"></script>
<script src="index.js"></script>
</body>
</html>

Related

How to iterate ViewBag names inside foreach loop?

I managed to find in SO questions regarding looping through ViewBag objects, but my issue is how to use iteration to name ViewBag inside of it.
But starting from the beginning. Inside of my Razor View I have a code, that triggers scripts depending on passed ViewBag:
#if (ViewBag.TermsChecked == "false")
{
<script type="text/javascript">
document.getElementById("termschecked").style.border = "2px solid #E24941";
</script>
}
else if (ViewBag.TermsChecked == "true")
{
<script type="text/javascript">
document.getElementById("termschecked").style.border = "unset";
</script>
}
#if (ViewBag.LoginCaptchaChecked == "false")
{
<script type="text/javascript">
document.getElementById("logincaptchachecked").style.border = "2px solid #E24941";
</script>
}
else if (ViewBag.LoginCaptchaChecked == "true")
{
<script type="text/javascript">
document.getElementById("logincaptchachecked").style.border = "unset";
</script>
}
#if (ViewBag.RegisterCaptchaChecked == "false")
{
<script type="text/javascript">
document.getElementById("registercaptchachecked").style.border = "2px solid #E24941";
</script>
}
else if (ViewBag.RegisterCaptchaChecked == "true")
{
<script type="text/javascript">
document.getElementById("registercaptchachecked").style.border = "unset";
</script>
}
#if (ViewBag.CaptchaChecked == "false")
{
<script type="text/javascript">
document.getElementById("captchachecked").style.border = "2px solid #E24941";
</script>
}
else if (ViewBag.CaptchaChecked == "true")
{
<script type="text/javascript">
document.getElementById("captchachecked").style.border = "unset";
</script>
}
To keep it DRY I want to create a loop through ViewBag names, but I am not sure how to pass item into ViewBag name in the loop. Until now I tried 2 approaches already, that did not work:
#{string[] viewbags = new string[] { ViewBag.TermsChecked, ViewBag.LoginCaptchaChecked, ViewBag.RegisterCaptchaChecked, ViewBag.CaptchaChecked };}
#foreach (string item in viewbags)
{
if (item == "false")
{
<script type="text/javascript">
document.getElementById("#item.ToLower()").style.border = "2px solid #E24941";
</script>
}
else if (item == "true")
{
<script type="text/javascript">
document.getElementById("#item.ToLower()").style.border = "unset";
</script>
}
}
and
#{string[] viewbags = new string[] { "TermsChecked", "LoginCaptchaChecked", "RegisterCaptchaChecked", "CaptchaChecked" }}
#foreach (string item in viewbags)
{
#if (ViewBag.item == "false")
{
<script type="text/javascript">
document.getElementById("#item.ToLower()").style.border = "2px solid #E24941";
</script>
}
else if (ViewBag.TermsChecked == "true")
{
<script type="text/javascript">
document.getElementById("#item.ToLower()").style.border = "unset";
</script>
}
}
Both are not triggering any script, like they should do.
You can try to modify your Viewbag like :
public IActionResult Index()
{
List<Item> items = new List<Item>();
items.Add(new Item { key = "LoginCaptchaChecked", value = "false" });
items.Add(new Item { key = "RegisterCaptchaChecked", value = "true" });
ViewBag.showHidelist = items;
return View();
}
public class Item {
public string key { get; set; }
public string value { get; set; }
}
And in page you can dynamically set the border with :
#foreach (var item in ViewBag.showHidelist)
{
if (#item.value=="true")
{
<script type="text/javascript">
document.getElementById("#item.key.ToLower()").style.border = "2px solid #E24941";
</script>
}
else
{
<script type="text/javascript">
document.getElementById("#item.key.ToLower()").style.border = "unset";
</script>
}
}
Using for can solve your problem.
Code:
#for (int i = 0; i < ViewBag.showHideList.Count(); i++)
{
Item itm = ViewBag.showHideList[i];
...
}

SurveyJS : How to implement captcha image challenge

I try implement custom widget follow guide https://surveyjs.io/Examples/Library/?id=custom-widget-select2-tagbox
but not show image challenge of captcha
how can i implement captcha image challenge for surveyjs form?
i find the way:
html:
{
type: "html",
name: "info",
html: "<div id='g-recaptcha'></div> <div class='form-group g-recaptcha' data-callback='verifyCaptcha' data-sitekey='" + recaptchaClientKey + "'></div>"
}
ts, js
survey.onCompleting.add(function (sender, options) {
debugger;
var response = grecaptcha.getResponse();
if (response.length == 0) {
document.getElementById('g-recaptcha').innerHTML =
'<span class="form-group text-danger validation-summary-errors" data-valmsg-summary="true"><ul><li>Google reCAPTCHA validation failed</li></ul ></span >';
options.allowComplete = false;
} else {
options.allowComplete = true;
}
});
#section Scripts{
<script type="text/javascript" src="~/js/signup/survey_config.js"></script>
<script src='https://www.google.com/recaptcha/api.js'></script>
<script>
function verifyCaptcha() {
document.getElementById('g-recaptcha').innerHTML = '';
}
</script>
}

YouTube iFrame API “setPlaybackQuality” not working

YouTube iFrame API “setPlaybackQuality” not working.i want to change video qulity to lowest.but i cant change it by the api.i used player.setPlaybackQuality('small').it not worked.
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<button id="change_quality">Change Quality</button>
<div id="player"></div>
<script>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: '6LV3JdR5aZw',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
$("#change_quality").click(function() {
event.target.playVideo();
var d=player.getPlaybackQuality()
console.log("before");
console.log(d);
player.setPlaybackQuality('small')
var v=player.getPlaybackQuality()
console.log("after");
console.log(v);
});
}
}
</script>
</body>
</html>
it is not working in youtube demo also
Demo

VueJS Data ForLoop Issue

I'm using forloop to check the items in my data in COMPONENT.
{
data:function(){
return {
items:[
{id:1,name:'John'},
{id:2,name:'FooBz'}
]
}
}
}
now I want to check the value first in console in ready hook of my component.
{
.....
ready:function(){
console.log(this.items);
// this return a [__ob__: Observer]
this.items.forEach(function(x,y){
............
});
}
}
the this.items return a '[ob: Observer]' which I can't iterate through because the length of that value is 0 it supposed to be 2.
EDIT:
this is strange on my JSBIN all are working but in my real code its not. Even though I copied my logic from my real code I'm using Laravel Elixir to compile my javascript and 1.0.24 version of Vue.
http://jsbin.com/gijaniqero/edit?html,js,console,output
Your code should be okay.
Just using your code, i have made demo. It should be okay
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<test_component></test_component>
</div>
<template id="test_component">
<div></div>
</template>
<script src="js/vue.js"></script>
<script>
var vm = new Vue({
el:'#app',
data: {
},
components : {
'test_component' : {
template : '#test_component',
data:function(){
return {
items:[
{id:1,name:'John'},
{id:2,name:'FooBz'}
]
}
},
ready : function(){
this.items.forEach(function(x,y){
console.log( 'id is : ' + x.id);
console.log( 'name is L ' + x.name);
console.log( 'key is ' + y);
});
}
}
}
})
</script>
</body>
</html>

How do I solve the conflict caused by my jQuery navigation plugin and javaScript file?

My jQuery navigation works- but now it's conflicting with a fadeIn and fadeOut effect (picture and greeting) so they are not showing up.
Here is a link to my page:http://bit.ly/1cr93gD
Here is the code that is on my final_project.js file for the fadeIn & fadeOut effects:
jQuery$(document).ready(function() {
$('#headshot').css('visibility','visible').hide().fadeIn(5000);
$('#greeting').css('visibility','visible').hide().toggle(9000);
var defaultH1 = parseInt($('h1').css('font-size'));
var defaultP = parseInt($('p').css('font-size'));
var count = 0;
var elements = ['p', 'h1'];
$('.minus').click(function(){
if ( count >= -1 ) {
$(elements).each(function(key, val) {
$(val).css('font-size', parseInt($(val).css('font-size'))-2);
});
count--;
};
});
$('.plus').click(function(){
if ( count <= 1 ) {
$(elements).each(function(key, val) {
$(val).css('font-size', parseInt($(val).css('font-size'))+2);
});
count++;
};
});
$('.reset').click(function(){
$('h1').css('font-size', defaultH1);
$('p').css('font-size', defaultP);
count = 0;
}
});
Your code has been tested it had some syntax error I have corrected it and it works fine, bellow is Working code
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js">
</script>
<script>
$(document).ready(function() {
$('#headshot').css('visibility','visible').hide().fadeIn(5000);
$('#greeting').css('visibility','visible').hide().toggle(9000);
var defaultH1 = parseInt($('h1').css('font-size'));
var defaultP = parseInt($('p').css('font-size'));
var count = 0;
var elements = ['p', 'h1'];
$('.minus').click(function(){
if ( count >= -1 ) {
$(elements).each(function(key, val) {
$(val).css('font-size', parseInt($(val).css('font-size'))-2);
});
count--;
};
});
$('.plus').click(function(){
if ( count <= 1 ) {
$(elements).each(function(key, val) {
$(val).css('font-size', parseInt($(val).css('font-size'))+2);
});
count++;
};
});
$('.reset').click(function(){
$('h1').css('font-size', defaultH1);
$('p').css('font-size', defaultP);
count = 0;
})
});
</script>
</head>
<body>
<h1>Testing the code</h1>
<button class="minus"> - </button>
<button class="plus"> + </button>
<button class="reset"> reset </button>
<p>This is a paragraph.</p>
<h1 id="greeting">Welcome</H1>
<img src="http://www.kveller.com/mayim-bialik/wp-content/uploads/2011/12/mayim-bialik-headshot-cropped.jpg" id="headshot"></img>
</body>
</html>
if you what to toggle between entities then look at bellow example to do it.
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js">
</script>
<script>
$(document).ready(function() {
$('#headshot').fadeOut(000);
$('#greeting').fadeOut(5000);
$('#headshot').fadeIn(5000);
setInterval(function(){
$('#headshot').fadeOut(5000);
$('#greeting').fadeIn(5000);
},10000);
setTimeout(function(){
setInterval(function(){
$('#headshot').fadeIn(5000);
$('#greeting').fadeOut(5000);
},10000);
},5000);
});
</script>
<style>
#greeting,#headshot {position:fixed;top:0px;left:0px;}
</style>
</head>
<body>
<h1 id="greeting" >Welcome</H1>
<img src="http://www.kveller.com/mayim-bialik/wp-content/uploads/2011/12/mayim-bialik-headshot-cropped.jpg" id="headshot" width="200px" height="200px"></img>
</body>
</html>
in this case both entities can be of same or different type.