I have been trying to display JSON data from one page to another on click.
For example, a user clicks on an image and it passes the same image/text to another page.
Here is my code
ygt.js
<h2 class="pet-name">${pet.name}
<h1 class="species">${pet.species}
</div>
<div></div></div>
</div>
</div>
`;
}
document.getElementById("app").innerHTML = `
<h1 class="app-title">Kids
${petsData.map(petTemplate).join("")}
`;
You can use localStorage to pass the values from one page to another. Let's say you have the books in one page and you want to pass the book name to another page.
In your books page, you can add a function like this:
function saveBook(bookName, link){
localStorage.setItem("bookName", bookName):
window.location.href = link
}
Then you can call this function in your onclick event.
<div class="olay" onclick="saveBook('The Book','${pet.href}');" style="cursor: pointer;">
When someone clicks on the book, it will save the value in the localStorage and redirect to the page you need.
In the second page, you can use a function to retrieve the saved value:
var bookName = localStorage.getItem('bookName');
More info on localStorage : https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
Related
I'm using the URL Params plugin to pull parameters into regular content using a short code. But I have to use a Raw HTML block to insert Typeform code into the page and I want to be able to pass a URL parameter into the Typeform code to track the source of the form submission.
I can't figure out how to do it. The form is working fine at: https://HelloExit.com/instant-valuation
But I want to be able to send people to https://HelloExit.com/instant-valuation/?source=XXXX and pull the XXXX into the Typeform code as the "source" value in the "data-url"
Here's what I tried:
<script>
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
var source = getUrlVars()["source"];
</script>
<div
class="typeform-widget"
data-url="https://xgenius.typeform.com/to/zZHPPk?source=<script>document.write(source)</script>"
data-transparency="100"
data-hide-headers=true
data-hide-footer=true
style="width: 100%; height: 500px;">
</div>
<!-- Typeform embed code -->
<script>(function() { var qs,js,q,s,d=document, gi=d.getElementById,
ce=d.createElement, gt=d.getElementsByTagName, id="typef_orm",
b="https://embed.typeform.com/"; if(!gi.call(d,id)) { js=ce.call(d,"script"); js.id=id;
js.src=b+"embed.js"; q=gt.call(d,"script")[0]; q.parentNode.insertBefore(js,q) } })()
</script><div style="font-family: Sans-Serif;font-size: 12px;color: #999;opacity: 0.5;padding-top: 5px;"> powered by Typeform</div>
Any assistance would be greatly appreciated!
You're close, but you'll need to use Javascript to alter the data-url attribute of your div.
// ...
var source = getUrlVars()["source"];
// concatenate the url with your source variable
var newUrl = `https://xgenius.typeform.com/to/zZHPPk?source=${source}`;
// get the element whose attributes you want to dynamically set
// https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
var widgetElement = document.querySelector('.typeform-widget');
// set the source attribute
// https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute
widgetElement.setAttribute('data-url', newUrl);
Test this carefully, as it might still end up with a race condition (that is, the Typeform embed code might start running before you've updated the data-url attribute that it references).
I'm tracking some asset downloads using Tag Manager. There are multiple downloadable assets on the page, each with a 'Download asset' button.
I want to create a single tag in tag manager to cover all of these downloads, using the event label to specify the type of asset: eg 'full-bleed image', 'facebook ad image' etc.
Ordinarily, I'd use the 'click text' or 'click URL' variables for this but I can't on this occasion. All of the download buttons have the same text (apparently, this can't be changed) and the URL just includes a CMS-generated asset number as opposed to a descriptive URL.
However, above each button there is a h4 that includes the name of the asset:
Is there any way to create a variable in tag manager that will scrape the content of the h4 just above the button when it's clicked?
I created a variable for the h4 but it just captures the content of the first h4 on the page (and not the one nearest to the button click).
<div class="content">
<h4>Full Bleed</h4>
<div class="copy">
<p>Perfect for social media.</p>
</div>
<div class="btn-container">
<a href="URL?assetNo=17232568" class="btn" >Download assets
</a>
</div>
</div>
Yes there is a way to do it. It requires some scraping.
You can create a new custom JavaScript variable and use built-in variable {{Click Element}} - then get it's parent node, e.g.:
{{Click Element}}.parentNode
This should return whole <div class="content"> element. Then simply search inside that element for <h4> like so:
{{Click Element}}.parentNode.getElementsByTagName("h4")[0]
this is your "Full Bleed" element. Remember that this returns an array, thus [0].
One thing to note is that when you click on your element:
<div class="btn-container">
<a href="URL?assetNo=17232568" class="btn" >Download assets
</a>
</div>
depending on where exactly you click the {{Click Element}} will sometimes be <div> element and sometimes <a> inside of it. This would break ".parentNode" functionality sometimes so you will need some checks. Below I write some pseudo code (not tested and messy):
Custom JavaScript variable:
function(){
var parent = {{Click Element}}.parentNode;
var value = "";
if(parent.className === "content"){
value = parent.getElementsByTagName("h4")[0]
}else{
value = parent.parentNode.getElementsByTagName("h4")[0]; // you need to go one level above
}
return value.innerText;
}
I wanna render show template into index template right after clicked element.
Some code(jade):
template(name="index")
ul
for post in posts
li
a(href="posts/1")= post.title
// render full post #1 here if link clicked
li
a(href="posts/2")= post.title
// render full post #2 here if link clicked
li
a(href="posts/3")= post.title
// render full post #3 here if link clicked
So I don't need to replace whole index template when user clicks show post link. I just need render show template right after link to this post.
Also I need to show only one post at same time, so if user clicks one post, then another, first one should be removed from DOM and second one should be rendered just in his place (right after show link).
How can I do that with meteor and Iron Router?
See Blaze.render or Blaze.renderWithData
Insert placeholders into your markup:
template(name="index")
ul
for post in posts
li
a(href="posts/1")= post.title
div(id="post1") // render full post #1 here if link clicked
li
a(href="posts/2")= post.title
div(id="post2") // render full post #2 here if link clicked
li
a(href="posts/3")= post.title
div(id="post3") // render full post #3 here if link clicked
Then setup your helpers:
Template.index.helpers({
'click a': function(ev){
... determine which link was clicked on
... pick the node to inject ex:
var node = $('#post2');
Blaze.render('postTemplate',node);
}
});
One way to do this would be to go ahead and render everything, but keep it hidden. Then you can add a click event handler that hides everything and shows only the thing that was clicked:
<template name='index'>
<ul>
{{#each posts}}
<li>
<a href='#' class='show-index-link' _id="{{_id}}"><!--Store _id so we can retrieve it in event handler-->
<div class='post-show-hide' id='post-show-hide-{{_id}}' style='display: none;'><!-- make it easy to select in the event handler-->
{{> post}}<!-- data context is the post in question -->
</div>
</li>
{{/each}}
</ul>
</template>
Then your event handler might look something like this:
Template.index.events({
'click .show-index-link': function(event) {
var _id = $(event.currentTarget).attr('_id'); // grab the ID of the post to show
event.preventDefault();
$('.post-show-hide').hide(); // hide all of them
$('#post-show-hide-' + _id).show(); // Show only the one we just clicked on
}
});
This seems the most straightforward way to accomplish this to me, but if you're concerned about the performance of sending all of the posts to the client, you could also consider having an event handler that subscribes to the post in question. That seems significantly more difficult (and if you're really worried about that sort of performance issue, you can get around it much more easily, e.g. with pagination), so unless you really need it, I'd stick to something simple like the solution above.
I am trying to implement searching in my Meteor app. I don't exactly understand how it ties together. At this point, I have this following code:
html:
<form class="navbar-search pull-left">
<input type="text" class="search-query" placeholder="Search">
</form>
js:
Template.menubar.events({
'keyup input.search-query': function (evt) {
console.log("Keyup value: " + evt.which);
if (evt.which === 13) {
console.log("Got an Enter keyup");
Session.set("searchQuery", "justATestVar");
}
}
});
I can see the values of keyup as I press different keys into the search box, so I know the event is being hit. Capturing the "enter" keyup also works, but pressing enter causes the enter site to reload and when I do:
Session.get("searchQuery")
it returns undefined.
I don't know if I'm handling this properly. Essentially, I just want to get the value from the search box and then use that value for making a search on my collection. Any help would be appreciated! Thank you.
You should really use a submit button for your search form to avoid ruining accessibility.
Using a submit button will also enable by default the behavior you're looking for : form submission on enter key pressed.
If you really want to get rid of the submit button, keep it in the DOM but use CSS to hide it.
It's very important to call preventDefault on the event you'll receive from "submit form" handler, if you forget to do so, the page will refresh ruining the meteor "Single Page App" experience (and by the way, page refresh will clear your Session variables, which is why you get an undefined value in the first place).
"submit form":function(event,template){
event.preventDefault();
Session.set("searchQuery",template.find(".search-query").value);
}
What is probably happening is your form is being submitted when you hit enter. Try an preventDefault(). Probably something like this would work:
Template.menubar.events({
'keyup input.search-query': function (evt) {
console.log("Keyup value: " + evt.which);
if (evt.which === 13) {
console.log("Got an Enter keyup");
Session.set("searchQuery", "justATestVar");
}
},
'submit form': function (evt) {
evt.preventDefault();
}
...
You could also try adding evt.preventDefault(); in your keyup but I think it's the form submission that's doing it.
In case anyone got here trying to implement the search function as well, I recommend the following:
meteor add matteodem:easy-search
On client and server:
Players = new Meteor.Collection('players');
// name is the field of the documents to search over
Players.initEasySearch('name');
On the client, make a template.html:
<template name="searchBox">
{{> esInput index="players" placeholder="Search..." }}
<ul>
{{#esEach index="players"}}
<li>Name of the player: {{name}}</li>
{{/esEach}}
</ul>
</template>
Reference
Using Meteor, I am trying to loop through and display a list of notes from a database with an option to delete each note.
Here is the HTML (using Handlebars.js)
<template name="Notes">
{{#each NoteArr}}
<div class="Note">
<h2>{{Title}}</h2>
<p>{{Body}}</p>
<span class="deleteNote">Delete</span>
</div>
{{/each}}
</template>
And here is the client Javascript
Template.Notes.events = {
"click .deleteNote" : function(){
noteID = $('.deleteNote').parent().attr("id");
Notes.remove({ID:noteID});
}
};
This grabs the first instance of .deleteNote, so unless I'm trying to delete the first one, that won't help. How can I grab the parent of the particular instance of .deleteNote that was clicked, not just the first one it finds?
The reason why the first element is deleted is.. in your .click event, you are accesssing the div directly as $('.deleteNote').parent() which grabs the first node in the html which has a class .deleteNode.
Now to remove the specific notes, from the collection: Every document in the collection has a unique _id attribute which is generated automatically. assign that unique _id of the document to the span element as <span id= "{{_id}}" class="deleteNote">Delete</span>.
So the cilck event will look like:
Template.Notes.events = {
"click .deleteNote" : function(e){
var noteID = e.currentTarget.id;
Notes.remove({_id:noteID});
}
};
And the template will look like:
<template name="Notes">
{{#each NoteArr}}
<div class="Note">
<h2>{{Title}}</h2>
<p>{{Body}}</p>
<span id= "{{_id}}" class="deleteNote">Delete</span>
</div>
{{/each}}
</template>
Untested code, but hope this will help solving your issue.
The _id of a note is stored in 'this' as well. In addition, the remove function accepts '_id' as a string. So this should work as well:
Template.Notes.events = {
'click .deleteNote': function(){ return Notes.remove(this._id)}
}
A few benefits here. Less querying the DOM for information. Less jQuery. Fewer lines of code to think about. Cleaner templates.