I have a quite rare problem, or I don't know since I am a beginner :)
I'm creating a DOM tree with ajax, the output is perfect, except that the functions I'm calling does not work. . If I create the same three with pure JavaScript. it actually calls the function. Well quite hard to explain, will show with some code.
function stickers(){
$(document).ready(function() {
$('#add-new-sticker-btn').click(function() {
$.get('xml/data.xml', function(data) {
$('#page-content-wrapper').empty();
$(data).find('car').each(function() {
var $car = $(this);
var sticker = '<div class="sticker">';
sticker += '<div class ="sticker-drag">' + '</div>';
sticker += '<textarea>' + $car.find('product').text() + '</textarea>';
sticker += '<div class="sticker-close">' + '</div>';
$('#page-content-wrapper').append(sticker);
});
});
return false;
});
});
movewrap(); // <!-- this is the function that I'm trying to call.
}
but If I instead write the pure javascript
function stickers(){
var sticker = createElementWithClass('div', 'sticker'),
textArea = document.createElement('textarea');
var stickerDrag = createElementWithClass('div','sticker-drag')
var stickerClose = createElementWithClass('div','sticker-close')
sticker.appendChild(stickerDrag);
sticker.appendChild(textArea);
sticker.appendChild(stickerClose);
document.getElementById('page-content-wrapper').appendChild(sticker);
movewrap();
} // its calling the moveWrap function.
Any ideas ?
Place the call to moveWrap at the end of your AJAX callback. Currently it's being called after the request is made, not after the response is received, and there won't be anything for it to do because the DOM elements aren't there yet.
Related
I'm sort of new to JS and bookmarklets.
I'm modifying some existing code; which is written like this (I'm oversimplifying the actual code for the education purposes):
javascript: 1 && function(e) {
var t = "";
t += "<style>",
t += ".somestyle-header{ background-color: #0171C5 !important }",
t += "</style>",
t += '<div class="somestyle-header">Test</div>',
t += "";
e("body").append("<div id='something'> </div>"), e("#something").append(t)
}($myvariable);
Now, this currently works and it creates a DIV called "something" and then appends everything on variable "t" to it. In other words it adds whatever is on variable "t" to the HTML of the current site (given that the site has the $myvariable set somewhere).
I'm trying to do something similar, but I have the following questions:
How can I remove that 1 at the very begining of the function and make it work?
How can I make it work on every page?, regardless of the
$myvariable at the end being present or not.
Also, if someone can explain what that 1 at the very beginning and that $myvariable at the very end are doing and why this code doesnt work if I remove any of those parts?
I was hoping I can do something like this:
javascript: (function() {
if (!($ = window.jQuery)) {
script = document.createElement( 'script' );
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
script.onload=launchTheSplash;
document.body.appendChild(script);
}
else {
launchTheSplash(e);
}
function launchTheSplash(e) {
var t = "";
t += "<style>",
t += ".somestyle-header{ background-color: #0171C5 !important }",
t += "</style>",
t += '<div class="somestyle-header">Test</div>',
t += "";
e("body").append("<div id='something'> </div>"), e("#something").append(t)
}
}());
So that:
I check for the existence of JQuery
I launch my bookmarklet regardless of the existence of the $myvariable
But my code doesn't seem to work at all if I remove the 1 at the beginning or the $myvariable at the end. If I do that I get an Uncaught TypeError: e is not a function
Hope this is clear enough. Thanks in advance!
Edit:
I've tried the suggestion below:
javascript: (function() {
if (!($ = window.jQuery)) {
script = document.createElement( 'script' );
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js';
script.onload=launchTheSplash();
document.body.appendChild(script);
}
else {
launchTheSplash();
}
function launchTheSplash(e = $) {
var t = "";
t += "<style>",
t += ".somestyle-header{ background-color: #011515 !important }",
t += "</style>",
t += '<div class="somestyle-header">Test</div>',
t += "";
e("body").append("<div id='something'> </div>"), e("#something").append(t);
}
}());
But it doesnt seem to work on certain pages; for example -if I try to run the bookmarklet in www.apple.com website it comes back with Uncaught TypeError: e is not a function
Any ideas appreciated! Thanks again!
In order to execute functions immediately, you can use IIFE(https://developer.mozilla.org/en-US/docs/Glossary/IIFE). The correct syntax to execute functions immediately is -
(function(text){
console.log(text);
})('Hello World')
In your case e is supposed to be jquery element, so whenever you are calling launch function you should pass $ in it.
Take a look at this snippet - https://jsitor.com/E8JW18YD-
I need to pass a json object to function, which is as mentioned below in a href, but this JS code is not getting evaluated. So can anyone suggest a workaroud or a solution for this?
function function_test(option,jsonObj){
displayMessage(str);
}
function function_prepare_div(){
var str ="";
var jsonResposneObj = getJson();//function to get jsonResponseObj
for(i=0;i<jsonResponseObj.length;i++){
str += "<a href='function_test( " + i + "," + jsonResposneObj.dataObj[i] +")'>1. " + jsonResposneObj.dataObj[i].objName + "</a></br>";
}
return str;
}
P.S. I cannot return the jsonResponse after function call.
Instead of using inlined JS, append the element using proper DOM methods, and then attach an event listener.
Eg something like
const a = container.appendChild(document.createElement('a'));
a.href = function_test(1, jsonResponse);
a.textContent = '1. ' + function_test(1, jsonResponse);
(make sure function_test returns a URL)
Functions (or any JavaScript for that matter) don't belong in an <a href=""> in the first place.
Hyperlinks are for navigation, not JavaScript hooks. Using them just to trigger some JavaScript is an incorrect use of the <a> tag. It was commonplace 20+ years ago (before we had web standards), but is woefully outdated and downright incorrect today. Using a hyperlink to trigger JavaScript is semantically incorrect and can cause issues for people who rely on assistive technologies (like screen readers) to navigate a page.
Just about any element that is valid in the body of a web page supports a click event and most are better suited to what you want to do.
What you need to do is register your function as the callback to the click event of some element, like this:
// An example of a JSON response
var jsonResponse = '{"key1":10,"key2":true,"key3":"foo"}';
// Get reference to any element that supports a click event that
// can be safely used as a JavaScript trigger
var span = document.getElementById("fakeLink");
// Set up an event handling callback function for the click event of the element
span.addEventListener("click", function(){
// Call the function and pass it any arguments needed
processJSON(1, jsonResponse, this);
});
// Do whatever you need to do in this function:
function processJSON(val, json, el){
console.log(val, json);
el.textContent = val + json;
}
/* Make element look & feel like a hyperlink */
#fakeLink { cursor:pointer; text-decoration:underline; }
#fakeLink:active { color:red; }
<span id="fakeLink">Click Me</span>
var json = {
foo: 'bar'
};
var func = function(data) {
alert(data.foo);
}
$('body').append("<button onclick='func(" + JSON.stringify(json) + ")'>BUTTON</button>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I am using Firebase child_added to watch for new entries being added to my database.
It seemed to work for a while but then I noticed some issues when leaving the connection idle. If I leave my app open for a prolonged period of time when Firebase returns duplicates. I think it maybe down to the connection being dropped and then established.
Here is my code.
getVoicemailList: function() {
var self = this;
var userId = firebase.auth().currentUser.uid;
firebase.database().ref('voicemails/' + userId).on('child_added', function(snapshot) {
var voicemail = snapshot.val();
self.addToCollection(voicemail.callerID, voicemail.timeReceived, voicemail.transcription, voicemail.audioURL);
});
},
addToCollection: function(callerID, timeReceived, transcription, audioURL) {
console.log(callerID)
var collectionList = $('.collapsible').length;
if(!collectionList) {
$('#main-content').append('<ul class="collapsible" data-collapsible="accordion"></ul>')
}
var output = '<li>';
output += '<div class="collapsible-header"><i class="material-icons">filter_drama</i>'+callerID+'</div>';
output += '<div class="collapsible-body">';
output += '<p><audio id="source" controls>';
output += '<source src="'+audioURL+'" type="audio/mpeg">';
output += '</audio></p>';
output += '<p>'+timeReceived+'</p>';
output += '<p>'+transcription+'</p>';
output += '</div>';
output += '</li>';
$('.collapsible').append(output);
$('.collapsible').collapsible();
},
If I understand your issue correctly, then it's something I've come across a few times. I believe the trick is to .empty() the existing data from within the .on call.
As an example, on my site we have goals that users can add. When they add a new Goal the .on call adds a new Goal to the bottom of their list.
I was having an issue where deleting a Goal would then duplicate the UI data.
In order to address the issue, I moved $(#goals").empty(); to within the .on call.
firebase.database().ref('users/' + user).on('value', function(snapshot) {
$("#goals").empty(); // This removes all all previously added goals
snapshot.forEach(function(data) {
var id = data.key;
var desc = data.val().desc;
var url = data.val().url || "https://unsplash.it/400?image=" + getRandomNumber();
displayGoal(id,desc,url);
});
// If you need to append anything after all the data has been added you can do it here. e.g. $("#goals").append("</div>");
});
I suspected that doing this would force all relevant UI items to reload but they don't. If I add a Goal it just pops up on the bottom of the list, if I remove a Goal the UI just removes the goal without any reloading or duplication.
So in your case you would add $('.collapsible').empty(); after the .on call and before var voicemail = snapshot.val();.
Note: Previously I would call $("#goals").empty() prior to the .on call.
I am trying to nest fadein and fadeout methods in order to get the following effect. I would like the characters in 10 seperate tags to one by one fadeout, change text and then fade in. With what I know about callback functions the following code should achieve that but the effect I am getting now is all the elements change simultaneously and the text change does not wait for the fadeout resulting in the text flashing and then fading out and in. What am I doing wrong!! Here is a simplified version of what I have currently.
HTML/PHP:
<?php
echo '<div onclick="addname(this)">';
for ($i=0; i<10; i++){
echo '<h1 id="temp'.$i.'">Y</h1>';
}
?>
Javascript
function addname(item){
//Other stuff that works fine
hideChar(0);
}
function hideChar(i){
if(i<10){
var tag = "temp" + i;
var x = document.getElementById(tag);
$(x).fadeOut(200, showChar(i));
}
}
function showChar(i){
var tag = "temp" + i;
var x = document.getElementById(tag);
var j = i+1;
$(x).html("X");
$(x).fadeIn(200, hideChar(j));
}
You're not passing your function as the callback properly. When you include the () - the function will be triggered immediately - omit the () to pass it along:
$(x).fadeOut(200, showChar);
The default parameters will be passed along. If you need something other than the default - you'll have to use an anonymous function to call yours:
$(x).fadeOut(200, function() {
showChar(i)
});
I'm having a problem generating a list of feed items (using Google Feeds API) triggered by a tap event on a list item. I can call the function on page load, and it works great. However, when I try to call the function on a "tap" event if generates a blank page.
Here is the list item I want to trigger the event on (on which I'm calling the 'tap' event):
<li id="welstech" class="listFeeds">
<a href="#">
<img src="_images/welstech-logo-db.jpg" alt="WELSTech" />
<h2>WELSTech Podcast</h2>
<p>Discussions about Tech & Ministry</p>
</a>
</li>
Here is the script I have placed at the bottom of the html page:
<script type="text/javascript>
$(document).on('tap', '.listFeeds', function() {
listAudioPosts("http://feeds.feedburner.com/welstech");
});
</script>
Here is the function that it calls:
function listAudioPosts(feedurl){
google.load("feeds", "1");
console.log("I'm still going 1");
function initialize() {
console.log("I'm still going 2");
var feed = new google.feeds.Feed(feedurl);
feed.setNumEntries(10)
var output = '<ul data-role="listview" data-split-icon="info">';
var name = "welstech";
feed.load(function(result) {
if (!result.error) {
for (var i = 0; i < result.feed.entries.length; i++) {
var entry = result.feed.entries[i];
var mediaGroups = result.feed.entries[i].mediaGroups[0].contents[0];
var stripContentSnippet = entry.contentSnippet.replace(/[^a-zA-Z 0-9.:-]+/g,'');
var stripaContentSnippet = stripContentSnippet.replace('lt--pagingfilter--gt','');
output += '<li>';
output += '<a href="#">';
output += '<h2>' + entry.title + '</h2>';
output += '<p>' + stripaContentSnippet + '</p>';
output += '</a>';
output += '</li>';
} // loop through all the feeds and create li elements
} // end of if statement
output += '</ul>';
$("#testtouchoutput").html(output).trigger('refresh');
$.mobile.changePage("#test");
}); // end feed.load (function(result)
} // end initialize function
google.setOnLoadCallback(initialize);
}
I know the function works, because I can call it on page load with this script at the bottom of my html page see below. I also know the function gets as far as the sub function initialize(), as I can see the console.log output before that sub function, but not the one after it:
<script type="text/javascript">
listAudioPosts("http://feeds.feedburner.com/welstech");
</script>
So the second the home page loads, the function runs and the page refreshes to the list I want to generate...except I want to generate it on a "tap" event.
I'm a fairly new jquery programmer, so I'm sure it is something obvious. What am I missing?
Thanks.
You didn't close the .on, try something like this:
<script type="text/javascript>
$(document).ready(function() {
var timeTouched;
$('.listFeeds').bind('touchstart', function() {
timeTouched = new Date().getTime();
}
$('.listFeeds').bind('touchend', function() {
if (new Date().getTime() - timeTouched < 200) { // Ended touch within 200 milliseconds, counts as a tap
listAudioPosts("http://feeds.feedburner.com/welstech");
}
});
});
</script>
Make sure if your script is above wherever the .listFeeds element is defined, you include the $(document).ready() part, else it will be unable to bind the event to that element.
UPDATE: tap doesn't seem to be an event, updated with a potential solution.
UPDATE 2: Trying with .bind instead of .on.