DOM elements not accessible after onsen pageinit in ons.ready - jquery-selectors

I am using the Onsen framework with jQuery and jQuery mobile, it appears that there is no way to catch the event that fires once the new page is loaded.
My current code, which executes in the index.html file (the master page)
<script src="scripts/jQuery.js"></script>
<script src="scripts/jquery.mobile.custom.min.js"></script>
<script src="scripts/app.js"></script>
<script>
ons.bootstrap();
ons.ready(function() {
$(document.body).on('pageinit', '#recentPage', function() {
initRecentPage();
});
});
in app.js is the following code
function initRecentPage() {
$("#yourReports").on("tap", ".showReport", recentShowReport);
var content = document.getElementById("yourReports");
ons.compile(content);
}
and the HTML:
<ons-page id="recentPage">
<ons-toolbar id="myToolbar">
<div id="toolBarTitle" class="center">Recent Checks</div>
<div class="right">
<ons-toolbar-button ng-click="mySlidingMenu.toggleMenu()">
<ons-icon icon="bars"></ons-icon>
</ons-toolbar-button>
</div>
</ons-toolbar>
<ons-scroller>
<h3 class="headingTitle"> Checks</h3>
<div id="Free" class="tabArea">
<ons-list id="yourReports">
</ons-list>
<ons-button id="clearFreeRecentButton">
<span id="clearRecentText" class="bold">Clear Recent Checks</span>
</ons-button>
</div>
</ons-scroller>
</ons-page>
in this instance the variable 'content' is always null. I've debuged significantly, and the element I am trying to get is not present when this event fires. It is loaded later.
So, the question is, how do I ensure that all of the content is present before using a selector. It feels like this is an onsen specific issue.

In the end I could only find one reliable way of making this work.
Essentially I had to wait, using setTimeout 300 milliseconds for the DOM elements to be ready. It feels like a hack, but honestly there is no other reliable way of making this behave. The app is in the app store and works well, so even though it seems like a hack, it works:
$(document).on('pageinit', '#homePage', function() {
initHomePage();
});
function initHomePage() {
setTimeout(function() {
setUpHomePage();
}, 300);
}

Move your $(document.body).on('pageinit', '#recentPage', function() { outside of ons.ready block.
JS
ons.bootstrap();
ons.ready(function() {
console.log("ready");
});
$(document.body).on('pageinit', '#recentPage', function() {
initRecentPage();
});
function initRecentPage() {
//$("#yourReports").on("tap", ".showReport", recentShowReport);
var content = document.getElementById("yourReports");
alert(content)
ons.compile(content);
}
I commented out a line because I do not have access to that "recentShowReport"
You can see how it works here: 'http://codepen.io/vnguyen972/pen/xCqDe'
The alert will show that 'content' is not NULL.
Hope this helps.

Related

Using a Vue3 component as a Leaflet popup

This previous SO question shows how we can use a Vue2 component as the content of a LeafletJS popup. I've been unable to get this working with Vue3.
Extracting the relevant section of my code, I have:
<script setup lang="ts">
import { ref } from 'vue'
import L, { type Content } from 'leaflet'
import type { FeatureCollection, Feature } from 'geojson'
import LeafletPopup from '#/components/LeafletPopup.vue'
// This ref will be matched by Vue to the element with the same ref name
const popupDialogElement = ref(null)
function addFeaturePopup(feature:Feature, layer:L.GeoJSON) {
if (popupDialogElement?.value !== null) {
const content:Content = popupDialogElement.value as HTMLElement
layer.bindPopup(() => content.$el)
}
}
</script>
<template>
<div class="map-container">
<section id="map">
</section>
<leaflet-popup ref="popupDialogElement" v-show="false">
</leaflet-popup>
</div>
</template>
This does produce a popup when I click on the map, but it has no content.
If, instead, I change line 14 to:
layer.bindPopup(() => content.$el.innerHTML)
then I do get a popup with the HTML markup I expect, but unsurprisingly I lose all of the Vue behaviours I need (event handling, etc).
Inspecting the addFeaturePopup function in the JS debugger, the content does seem to be an instance of HTMLElement, so I'm not sure why it's not working to pass it to Leaflet's bindPopup method. I assume this has something to do with how Vue3 handles references, but as yet I can't see a way around it.
Update 2022-06-09
As requested, here's the console.log output: I've put it in a gist as it's quite long
So just to document the solution I ended up using, I needed to add an additional style rule in addition to the general skeleton outlined in the question:
<style>
.leaflet-popup-content >* {
display: block !important;
}
</style>
This overrides the display:none that is attached to the DOM node by v-show=false. It would be nice not to need the !important, but I wasn't able to make the rule selective enough in my experiments.

why my Riot JS update isn't working?

So I'm learning Riot JS, following a guide. Gives an example explaining step by step.
And adds a "this.update()" to update the riot js variables. Now, it is working for him, but not for me. Can you guys tell me why?
Here's the code.
This is the index.html
<body>
<script src="bower_components/riot/riot.min.js" type="text/javascript"></script>
<script src="tags/all.js" type="text/javascript"></script>
<contact-list></contact-list>
<script>
riot.mount('contact-list', {callback: tagCallback});
function tagCallback(theTag) {
console.log('callback executed');
var request = new XMLHttpRequest();
request.open('GET', 'people.json', true);
request.onload = function() {
if(request.status == 200) {
var data = JSON.parse(request.responseText);
console.log(data);
theTag.trigger('data_loaded', data);
}
}
setTimeout(function() {
request.send();
},2000);
}
</script>
</body>
And this is my contact-list.tag
<contact-list>
<h1>Contacts</h1>
<ul>
<li each={p in opts.people}>{p.first} {p.last}</li>
</ul>
<script>
this.on('mount', function() {
console.log('Riot mount event fired');
opts.callback(this);
})
this.on('data_loaded', function(peeps) {
console.log(peeps);
opts.people = peeps;
this.update();
})
</script>
</contact-list>
After debugging with the console.logs I can see i'm retrieving data correctly from my JSON file, my contact list data is there. But the bullet list isn't updated. It's displayed empty.
Is there any reason for using a callback function?
If not, move your callback function into the tag and update it directly after assigning your fetched data to your tags variable.
Look at the sources in riotgear:
https://github.com/RiotGear/rg/blob/master/tags/rg-include/rg-include.tag
For me it was a perfect example.
Oh nevermind guys, sorry. Don't know how actually the example of the guy in the video worked. Because I had to pass data.people on the html trigger event. Otherwise i was passing a plane Object with an Array in it.

Call a function after a form is submitted using jquery

I'm trying to call a function after any form with the class shown below is submitted. However, this doesn't seem to be working for me (the form submits, but the submit button remains active and the loading image is not shown).
$(document).ready(function() {
$('.uniForm').submit(function() {
$('#loadingImage').show();
$(':submit',this).attr('disabled','disabled');
return true;
});
});
Here's some HTML:
<form class="uniForm" id="formABC">
//...form.... here
</form>
<img src="loadimage.gif" style="display: none;" id="loadingImage">
does anyone see anything inherently wrong with this that would be preventing things from working correctly?
I have a feeling it's just not being called correctly. Can I call it myself via some HTML like this?
<button type="button" class="primaryAction" alt="Submit Form" onclick="$('#formABC').submit();">Submit Form</button>
Following your comment, it seems the binding of the handler function to the submit event might be taking place before the form element has been loaded into the DOM.
Ideally, you should bind event handlers only after the DOM has finished loading.
For example:
$(document).ready(function() {
$('.uniForm').submit(function() {
...
});
});
Put an id on the submit input/button and try this:
$('#mySubmitButton').click(function(e) {
e.preventDefault();
e.stopPropagation();
$(this).attr('disabled','disabled');
$('#loadingImage').show(function() {
$(this.form).submit();
});
});
There is a jQuery plugin named jQuery Form Plugin which helps to submit your form from ajax without refresh and then you can do the rest of actions on its success (which occurs exactly after successful form submission):
jQuery(document).ready(function () {
jQuery('#my_submit_button').click(function (e) {
jQuery(this.form).ajaxSubmit({
target: false,
success: function ()
{
your_other_stuff();
},
});
});
});
function your_other_stuff(){
// rest of things
}
Try something else:
$('.uniForm input[type=submit]').click(function(){
$('.uniForm').submit();
//doStuffafterSubmit
});

How to get clicked elelment in <fb:visible-to-connection>-context?

It seems FB have removed the possibility to get the the clicked element (i.e. this) in the context of <fb:visible-to-connection>.
I.e:
<a onclick="doSomething(this);">test</a>
<script>
function doSomething(this) {
console.log(this);
}
<script>
Will give the following in Firebug:
Object { PRIV_obj=a, appendChild=function(), insertBefore=function(), more...}
Whereas
<fb:visible-to-connection>
<a onclick="doSomething(this);">test</a>
<fb:else>
</fb:else>
<a onclick="doSomething(this);">test</a>
</fb:visible-to-connection>
<script type="text/javascript">
function doSomething(element) {
console.log(element);
}
</script>
Will give:
null
Is this a temporary bug in FBJS or due to some new feature?
How do I get hold of "this" in the second example?
This was changed for security reasons, you can't access HTML elements inside FMBL elements any more - the initial bug report (which was closed as a 'by design') was about using getElementById but I believe this is the same cause

javascript "window.history.forward(1);" not working

I'm trying to prevent the back button from working on one of my asp.net mvc pages.
I've read a couple of places that if i put "window.history.forward(1);" in my page it will prevent the back button from working on a given page.
This is what I did in my page:
<script type="text/javascript">
$(document).ready(function () {
window.history.forward(1);
});
</script>
It doesn't seem to be working. Am I using this incorrectly or is this approach wrong? thanks.
The way I've seen this trick used is to put history.forward() on every page before the page where you don't want the back button to work, then every time the user hits the back button it forwards them back to where they were. The common use is to prevent others from returning to a page (usually in a given, linear sequence) once they have progressed. This is sometimes used in the sign-in sequence for banking websites, for example.
As far as I know, there is no way to actually disable the back button. Sometimes people get around this by opening the page in a new window, which will not have a history of pages preceding it, and thus nothing to go back to. Others simply display a warning message before going back to inform a user that they may lose unsaved data, if that is the main concern.
That said, maybe this will help you: http://viralpatel.net/blogs/disable-back-button-browser-javascript/
maybe:...
<script type="text/javascript">
function disableBackButton()
{
window.history.forward();
}
setTimeout("disableBackButton()", 0);
$(document).ready(function () {
disableBackButton();
});
</script>
Use on the page in which you don't want back button to work.
window.history.forward(1);
This is working for me... Hope it helpful for you..
<script type="text/javascript">
window.history.forward();
function noBack(){
window.history.forward();
}
</script>
$(document).ready(function() {
noBack();
});
You can use
history.go(index)
index =0 //for the current page.
index>0 //e.g 1,2 for forward navigation
index<0 //e.g -1,-2 for backward navigation
history.go(-2)
<SCRIPT type="text/javascript">
window.history.forward();
function noBack() { window.history.forward(); }
</SCRIPT>
And in html Body tag write the following code.
<body onload="noBack();" onpageshow="if (event.persisted) noBack();" onunload=" " >
Try this, it worked for me.
Not sure if this is relevant but I found it and it might be worth a try:
<script type="text/javascript">
function preventBack() {
window.history.forward();
}
setTimeout("preventBack()", 0);
window.onunload = function() {
null
};
</script>
<script>
function preventBack() {
window.history.forward();
}
setTimeout("preventBack()", 0);
window.onunload = function () {
null
};
</script>
window.history.forward();
function noBack()
{
window.history.forward();
}
function setit() {
noBack();
}
<script>
function preventBack() {
window.history.forward();
}
setTimeout("preventBack()", 0);
window.onunload = function () {
null
};
</script>
The code needs to be on the page infront as well as the page you require for it to work