Function only working once - javascript

I am working on a map based project and have been using this library to pull info from Google about locations on the map - https://github.com/peledies/google-places
I have created the bellow test to make sure that none of the map based code was causing issues and to show you what is wrong.
The idea is that you can click a button which will pass a Google Place ID to the getInfo() function which will use the library and pull info from Google and display it on the page.
The problem is that this only works once. If you click the other location button nothing appears to happen. The information isn't being updated with info from the new location.
I have even added a clear button which will remove anything in the google related divs on the page.
I have put a console.log in the function and can see that when a button is clicked the ID is being passed to it.
I don't know what could be causing this and Google Dev Console does not show any errors.
function getInfo(p) {
console.log(p);
$("#google-reviews").googlePlaces({
placeId: p,
render: ['reviews', 'address', 'phone', 'hours'],
min_rating: 1,
max_rows: 3,
//rotateTime:5000,
schema: {
displayElement: '#schema', // optional, will use "#schema" by default
beforeText: 'Googlers rated',
middleText: 'based on',
afterText: 'awesome reviewers.',
type: 'Hostel',
},
address: {
displayElement: "#google-address" // optional, will use "#google-address" by default
},
phone: {
displayElement: "#google-phone" // optional, will use "#google-phone" by default
},
hours: {
displayElement: "#google-hours" // optional, will use "#google-hours" by default
}
});
}
function clearInfo() {
document.getElementById('schema').innerHTML = "";
document.getElementById('google-reviews').innerHTML = "";
document.getElementById('google-address').innerHTML = "";
document.getElementById('google-phone').innerHTML = "";
document.getElementById('google-hours').innerHTML = "";
}
.review-stars ul {
display: inline-block;
list-style: none;
}
.review-stars ul li {
float: left;
margin-right: 5px;
}
.review-stars ul li i {
color: #E4B248;
font-size: 12px;
}
/*color: #E4B248;*/
.review-stars ul li i.inactive {
color: #c6c6c6;
}
.star:after {
content: "\2605";
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places"></script>
<button onclick="getInfo('ChIJ7aUBOtBqdkgRMzcGmyqWyxM')">Location 1 (Watford)</button>
<button onclick="getInfo('ChIJ3xiQIe6g2EcRdkyT0iS5GNU')">Location 2 (Buckhurst Hill)</button>
<button onclick="clearInfo()">Clear</button>
<br>
<div id="schema">
<b>Schema - </b>
</div>
<div id="google-reviews"></div>
<div id="google-address"></div>
<div id="google-phone"></div>
<div id="google-hours"></div>
<script src="https://code.jquery.com/jquery-2.2.4.min.js" crossorigin="anonymous"></script>
<script src="https://rawgit.com/peledies/google-places/master/google-places.js"></script>

By looking at the plugin's code, it seems that it can only be initialised once. Beside the plugin, it also adds a googlePlaces function directly to the jQuery object. You can use that function instead, here is an example:
function getInfo(p) {
clearInfo();
$.googlePlaces($("#google-reviews"), {
placeId: p,
render: ['reviews', 'address', 'phone', 'hours'],
min_rating: 1,
max_rows: 3,
//rotateTime:5000,
schema: {
displayElement: '#schema', // optional, will use "#schema" by default
beforeText: 'Googlers rated',
middleText: 'based on',
afterText: 'awesome reviewers.',
type: 'Hostel',
},
address: {
displayElement: "#google-address" // optional, will use "#google-address" by default
},
phone: {
displayElement: "#google-phone" // optional, will use "#google-phone" by default
},
hours: {
displayElement: "#google-hours" // optional, will use "#google-hours" by default
}
});
}
function clearInfo() {
document.getElementById('schema').innerHTML = "";
document.getElementById('google-reviews').innerHTML = "";
document.getElementById('google-address').innerHTML = "";
document.getElementById('google-phone').innerHTML = "";
document.getElementById('google-hours').innerHTML = "";
}
.review-stars ul {
display: inline-block;
list-style: none;
}
.review-stars ul li {
float: left;
margin-right: 5px;
}
.review-stars ul li i {
color: #E4B248;
font-size: 12px;
}
/*color: #E4B248;*/
.review-stars ul li i.inactive {
color: #c6c6c6;
}
.star:after {
content: "\2605";
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places"></script>
<button onclick="getInfo('ChIJ7aUBOtBqdkgRMzcGmyqWyxM')">Location 1 (Watford)</button>
<button onclick="getInfo('ChIJ3xiQIe6g2EcRdkyT0iS5GNU')">Location 2 (Buckhurst Hill)</button>
<br>
<div id="schema">
<b>Schema - </b>
</div>
<div id="google-reviews"></div>
<div id="google-address"></div>
<div id="google-phone"></div>
<div id="google-hours"></div>
<script src="https://code.jquery.com/jquery-2.2.4.min.js" crossorigin="anonymous"></script>
<script src="https://rawgit.com/peledies/google-places/master/google-places.js"></script>

Related

How can I handle events in datalist options in vuejs?

I have a requirement where I have to suggest in the data list and when a user selects any of the datalist options, I have to update other input fields accordingly.
Here is my input field and Datalist code.
<input type="text" v-model="party.name" class="form-control form-control-sm shadow-sm" #input="searchPartyByName()" placeholder="Party name" list="queriedParties"/>
<datalist id="queriedParties">
<option v-for="party in queriedParties">{{party.name}}</option>
</datalist>
Now, what I want is, When a user hits enter or click on specific data list option, I want to update my this input field (Which is by default with data list) but I also want to set other form fields.
I have bound other form fields with my party data object. So, Only if I can update my party data object by any event on datalist option, I will be happy! I want something like this.
<option v-for="party in queriedParties" #click="setParty(party)">{{party.name}}</option>
I already tried the above-given example but it's not working. I also tried with #change but it's not working too!
Is there any way to accomplish this? I checked almost all the articles, jsfiddles and codepens available but none of them solves my issue.
datalist doesn't have events but the input does. You should do the following:
<template>
<input type="text" v-model="party.name" .... />
<datalist id="queriedParties">
<option v-for="party in queriedParties">{{party.name}}</option>
</datalist>
</template>
<script>
export default {
watch: {
party: {
deep: true,
handler (old_party, new_party) {
if (old_party.name !== new_party.name) this.searchPartyByName(new_party.name)
}
}
}
</script>
It seems that your queriedParties is an array of objects. Does it work if you have just an array of strings?
For objects use something along these lines:
<template>
<div class="sourceselection">
<div>
<div class="jumbotron">
<h2><span class="glyphicon glyphicon-list-alt"></span> News List</h2>
<h4>Select News Source</h4>
<input v-model="source" list="newssources-list" v-on:input="sourceChanged"
name="source-selection" id="source-selection" class="form-control"
placeholder="Please specify news source ..."/>
<datalist id="newssources-list">
<option v-for="source in sources" v-bind:value="source.name" v-bind:label="source.name"></option>
</datalist>
<div v-if="deepSource">
<h6>{{deepSource.description}}</h6>
<a v-bind:href="deepSource.url" class="btn btn-primary" target="_blank">Go To {{deepSource.name}} Website</a>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'sourceselection',
data () {
return {
sources: [],
source: '',
deepSource: ''
}
},
methods: {
sourceChanged: function(e) {
console.log("source = "+this.source+" new value = "+e.target.value);
var newSource = e.target.value;
// only action if value is different from current deepSource
if (newSource!= this.deepSource.name) {
for (var i=0; i<this.sources.length; i++) {
if (this.sources[i].name == newSource) {
this.deepSource = this.sources[i];
this.source = this.deepSource.name;
}
}
this.$emit('sourceChanged', this.deepSource.id);
}
}
},
created: function () {
var api = "https://newsapi.org/v1/sources?language=en";
this.axios.get(api).then((response) => {
this.sources = response.data.sources;
});
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
There is no event in datalist, so you can't handle, you'd better write your own list. Here is a example open in codepen:
//pug
#app
.form-group.has-feedback
input.input-search.form-control(type='text', v-model='word', placeholder='Search')
ul#list(v-if='Object.keys(filtered_projects).length > 0')
li(v-for='(value, key) in filtered_projects', #click='gotoProjectPage(key)')
span {{value}}
p {{key}}
span.glyphicon.glyphicon-search.form-control-feedback
/*css*/
body {
margin: 10px;
}
#app {
width: 400px;
}
#list {
font-size: 12px;
list-style: none;
margin: 0;
padding: 5px 0;
background-color: white;
border-radius: 0 0 5px 5px;
border: 1px #ccc solid;
}
#list li {
display: block;
padding: 5px 15px;
}
#list li:hover {
background-color: #ccc;
}
#list li span {
font-weight: 550;
}
#list li p {
margin: 5px 0 0;
}
//js
var app = new Vue({
el: '#app',
data: {
word: '',
projects: {"DataCenterMetro":"TEST1","IFF_Handway":"国际香料","SPH_Handway":"上药控股广东有限公司空调系统","QingTang_GZ":"广州地铁_清塘站","BTE_Handway":"白天鹅宾馆","NSSC_SZ":"深圳地铁_南山书城站","TA0301_Handway":"天安云谷二期"}
},
computed: {
filtered_projects: function () {
var vm = this, result = {};
if (vm.word) {
for(var key in vm.projects) {
if(key.toLowerCase().indexOf(vm.word) != -1 || vm.projects[key].toLowerCase().indexOf(vm.word) != -1)
result[key] = vm.projects[key];
}
}
return result;
}
},
created: function () {
var vm = this;
//TODO get projects
},
methods: {
gotoProjectPage: function (key) {
console.log('/map_login?project=' + key);
//TODO handle
}
},
});

initializing empty form breaks page; knockoutJS

using knockoutjs I want to have forms that allow infinite choices, but I need the form to display so the user knows it exist. I'm ok with starting with 3 forms, so I'd like to initialize empty objects when the page renders. For some reason, when I initialize one object it breaks my code:
function Task(data) {
this.title=ko.observable(data.title);
this.isDone=ko.observable(data.isDone);
}
function TaskListViewModel() {
// Data
var self=this;
self.tasks=ko.observableArray([]);
// self.tasks.push({'title': ''})
self.newTaskText=ko.observable();
self.incompleteTasks=ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(), function(task) {
return !task.isDone()
});
});
// Operations
self.addTask=function() {
self.tasks.push(new Task({
title: this.newTaskText()
}));
self.newTaskText("");
};
self.removeTask=function(task) {
self.tasks.destroy(task)
};
self.incompleteTasks=ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(),
function(task) {
return !task.isDone() && !task._destroy
});
});
self.save=function() {
$.ajax(".", {
data: ko.toJSON({
tasks: self.tasks
}),
type: "post",
contentType: "application/json",
success: function(result) {
alert(result)
}
});
};
// load initial state from server, convert to tasks, then add em to self.tasks
$.getJSON(".", function(allData) {
var mappedTasks=$.map(allData, function(item) {
return new Task(item)
});
self.tasks(mappedTasks);
});
self.tasks.push({'title': ''})
}
ko.applyBindings(new TaskListViewModel());
body { font-family: Helvetica, Arial }
input:not([type]), input[type=text], input[type=password], select { background-color: #FFFFCC; border: 1px solid gray; padding: 2px; }
.codeRunner ul {list-style-type: none; margin: 1em 0; background-color: #cde; padding: 1em; border-radius: 0.5em;}
.codeRunner ul li a { color: Gray; font-size: 90%; text-decoration: none }
.codeRunner ul li a:hover { text-decoration: underline }
.codeRunner input:not([type]), input[type=text] { width: 30em; }
.codeRunner input[disabled] { text-decoration: line-through; border-color: Silver; background-color: Silver; }
.codeRunner textarea { width: 30em; height: 6em; }
.codeRunner form { margin-top: 1em; margin-bottom: 1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body class="codeRunner">
<h3> Stuff </h3>
<div data-bind="foreach: tasks, visible: tasks().length > 0">
<p data-bind="value: title"></p>
</div>
<ul data-bind="foreach: tasks, visible: tasks().length > 0">
<li>
<input data-bind="value: title, disable: isDone" />
Delete
</li>
</ul>
You have <b data-bind="text: incompleteTasks().length"> </b> incomplete task(s)
<span data-bind="visible: incompleteTasks().length == 0"> -it 's beer time!</span>
<form data-bind="submit: addTask"><button type="submit">Add</button></form>
<script>
</script>
</body>
What is the pattern in knockout to initialize safely with this block of JS? Thank you
The reason you're getting an error is because the isDone property in your initial task was not being set. You also already have a Task viewModel, so why not use it to initialize your array? I've just used an IIFE (immediately-Invoked Function Expression) to initialize new tasks by newing up Task in a for loop. You can do this manually or in whichever way you prefer.
Also be aware of your use of the this keyword. See self.addTask in your code.
Im not sure if this is exactly what you're looking for but I assume you'd need a text input to enter newTaskText or am I missing something? Anyway, this seems to work. Hope is answers your question.
function Task(data) {
this.title = ko.observable(data.title);
this.isDone = ko.observable(data.isDone || false);
}
function TaskListViewModel() {
// Data
var self = this;
self.tasks = ko.observableArray([]);
// self.tasks.push({'title': ''})
self.newTaskText = ko.observable();
self.incompleteTasks = ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(), function(task) {
return !task.isDone()
});
});
// Operations
self.addTask = function() {
self.tasks.push(new Task({
title: self.newTaskText(),
isDone: false
}));
self.newTaskText("");
};
self.removeTask = function(task) {
self.tasks.destroy(task)
};
self.incompleteTasks = ko.computed(function() {
return ko.utils.arrayFilter(self.tasks(),
function(task) {
return !task.isDone() && !task._destroy
});
});
(function(numTasks) {
for (var x = 0; x < numTasks; x++) {
self.tasks.push(new Task({
title: ""
}));
}
})(3)
}
ko.applyBindings(new TaskListViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body class="codeRunner">
<h3> Stuff </h3>
<input data-bind="textInput: newTaskText" type="text" />
<input data-bind="click: addTask" type="button" value="Add Task" />
<div data-bind="foreach: tasks, visible: tasks().length > 0">
<p data-bind="value: title"></p>
</div>
<ul data-bind="foreach: tasks, visible: tasks().length > 0">
<li>
<input data-bind="value: title, disable: isDone" />
Delete
</li>
</ul>
You have <b data-bind="text: incompleteTasks().length"> </b> incomplete task(s)
<span data-bind="visible: incompleteTasks().length == 0"> -it 's beer time!</span>
<script>
</script>
</body>

Node Jquery load pages into div error

// Userlist data array for filling in info box
var userListData = [];
// DOM Ready =============================================================
$(document).ready(function() {
// Populate the user table on initial page load
populateTable();
// Username link click
$('#userList table tbody').on('click', 'td a.linkshowuser', showUserInfo);
// Add User button click
$('#btnAddUser').on('click', addUser);
// Delete User link click
$('#userList table tbody').on('click', 'td a.linkdeleteuser', deleteUser);
//Set Default page to Home.html
$('#content').load('views/home.html');
//Call navBar function
navBar();
projectBtn();
});
// Functions =============================================================
//Navbar function
function navBar() {
$('ul#navtest li a').click(function() {
var page = $(this).attr('title');
$('#content').fadeOut(400);
setTimeout(function(){$('#content').load('views/' + page + '.html')}, 400);
$('#content').fadeIn(400);
return false;
});
}
function projectBtn() {
$('a.projectbutton').click(function() {
var page = $(this).attr('title');
$('#content').fadeOut(400);
setTimeout(function(){$('#content').load('views/' + page + '.html')}, 400);
$('#content').fadeIn(400);
return false;
});
}
// Fill table with data
function populateTable() {
// Empty content string
var tableContent = '';
// jQuery AJAX call for JSON
$.getJSON( '/users/userlist', function( data ) {
// Stick our user data array into a userlist variable in the global object
userListData = data;
// For each item in our JSON, add a table row and cells to the content string
$.each(data, function(){
tableContent += '<tr>';
tableContent += '<td>' + this.username + '</td>';
tableContent += '<td>' + this.email + '</td>';
tableContent += '<td>delete</td>';
tableContent += '</tr>';
});
// Inject the whole content string into our existing HTML table
$('#userList table tbody').html(tableContent);
});
};
// Show User Info
function showUserInfo(event) {
// Prevent Link from Firing
event.preventDefault();
// Retrieve username from link rel attribute
var thisUserName = $(this).attr('rel');
// Get Index of object based on id value
var arrayPosition = userListData.map(function(arrayItem) { return arrayItem.username; }).indexOf(thisUserName);
// Get our User Object
var thisUserObject = userListData[arrayPosition];
//Populate Info Box
$('#userInfoName').text(thisUserObject.fullname);
$('#userInfoAge').text(thisUserObject.age);
$('#userInfoGender').text(thisUserObject.gender);
$('#userInfoLocation').text(thisUserObject.location);
};
// Add User
function addUser(event) {
event.preventDefault();
// Super basic validation - increase errorCount variable if any fields are blank
var errorCount = 0;
$('#addUser input').each(function(index, val) {
if($(this).val() === '') { errorCount++; }
});
// Check and make sure errorCount's still at zero
if(errorCount === 0) {
// If it is, compile all user info into one object
var newUser = {
'username': $('#addUser fieldset input#inputUserName').val(),
'email': $('#addUser fieldset input#inputUserEmail').val(),
'fullname': $('#addUser fieldset input#inputUserFullname').val(),
'age': $('#addUser fieldset input#inputUserAge').val(),
'location': $('#addUser fieldset input#inputUserLocation').val(),
'gender': $('#addUser fieldset input#inputUserGender').val()
}
// Use AJAX to post the object to our adduser service
$.ajax({
type: 'POST',
data: newUser,
url: '/users/adduser',
dataType: 'JSON'
}).done(function( response ) {
// Check for successful (blank) response
if (response.msg === '') {
// Clear the form inputs
$('#addUser fieldset input').val('');
// Update the table
populateTable();
}
else {
// If something goes wrong, alert the error message that our service returned
alert('Error: ' + response.msg);
}
});
}
else {
// If errorCount is more than 0, error out
alert('Please fill in all fields');
return false;
}
};
// Delete User
function deleteUser(event) {
event.preventDefault();
// Pop up a confirmation dialog
var confirmation = confirm('Are you sure you want to delete this user?');
// Check and make sure the user confirmed
if (confirmation === true) {
// If they did, do our delete
$.ajax({
type: 'DELETE',
url: '/users/deleteuser/' + $(this).attr('rel')
}).done(function( response ) {
// Check for a successful (blank) response
if (response.msg === '') {
}
else {
alert('Error: ' + response.msg);
}
// Update the table
populateTable();
});
}
else {
// If they said no to the confirm, do nothing
return false;
}
};
.border {
border: 4px solid black; }
.back2 {
background-color: #232323; }
.marginleft {
margin-left: 8%; }
.margin {
margin-right: 4%;
margin-left: 4%;
margin-top: 2%;
margin-bottom: 2%; }
.padding {
padding: 1%; }
.margintop {
margin-top: 1%; }
.margintop2 {
margin-top: 5%; }
.iconmargintop {
margin-top: 50px; }
.fill {
height: 100%;
width: 100%; }
p {
color: #ffffff; }
label {
color: #ffffff; }
h1 {
color: #ffffff; }
h2 {
color: #ffffff; }
th {
color: #ffffff; }
span {
color: #ffffff; }
h3 {
color: #ffffff; }
.projectseltext {
padding: 1%;
margin: 1%; }
.background {
background-color: #333333;
position: relative;
height: 100%; }
#blacktext {
color: black; }
.disablelink {
pointer-events: none;
cursor: default; }
.nav {
background-color: #b2b2b2; }
.nav a {
color: #ffffff;
font-size: 11px;
font-weight: bold;
padding: 14px 10px;
text-transform: uppercase; }
.nav li {
display: inline; }
.back1 {
background-color: #0c0c0c; }
.fit {
height: 100%;
width: 100%; }
.well {
background-color: #333333; }
.backg1 {
background-color: #333333; }
<html>
<head>
<meta name="generator"
content="HTML Tidy for HTML5 (experimental) for Windows https://github.com/w3c/tidy-html5/tree/c63cc39" />
<title></title>
</head>
<body>
<div id="project">
<div class="container-fluid row">
<a href="#" title="projectnew" class="projectbutton">
<div class="back2 col-md-11 margin border">
<img src="images/ph.jpg" class="thumbnail margin col-md-3" style="width:150px;" />
<h1 class="margin" style="margin-top:75px;">New Projects</h1>
</div>
</a>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta name="generator"
content="HTML Tidy for HTML5 (experimental) for Windows https://github.com/w3c/tidy-html5/tree/c63cc39" />
<link rel="stylesheet" href="stylesheets/bootstrap.min.css" />
<link rel="stylesheet" href="stylesheets/main.css" />
<script src="build/js/jquery-2.2.4.min.js"></script>
<script src="build/js/bootstrap.min.js"></script>
<script src="build/js/global.js"></script>
<title></title>
</head>
<body class="background">
<div class="container-fluid nav navbar-inverse">
<ul id="navtest" class="margintop">
<li>
Home
</li>
<li>
Projects
</li>
<li>
Contact
</li>
<li>
Resume
</li>
<li>
About
</li>
<li>
Database
</li>
</ul>
</div>
<div id='content' class="tab-content" />
</body>
</html>
<html>
<head>
<meta name="generator"
content="HTML Tidy for HTML5 (experimental) for Windows https://github.com/w3c/tidy-html5/tree/c63cc39" />
<title></title>
</head>
<body>
<div id="projectnew">
<div class="row">
<div class="container col-md-12 margintop marginleft">
Back
</div>
<div class="container-fluid margin">
<a href="" data-toggle="tab">
<div class="back2 col-md-11 margin border">
<img src="images/ph.jpg" class="thumbnail margin" style="width:150px" />
<h1 class="margin">Comming soon.</h1>
</div>
</a>
</div>
</div>
</div>
</body>
</html>
This file is temporary, i know the contents wont do anything.
The function navBar works perfectly, however when trying to apply the same method to another class and div it seems to fail.
Whenever i click on the projectbutton class it redirects to error.html. For some reason the javascript is not seeing/handling the class on click and the href being an unsupported type redirects me to error.html. However i'm not sure what is wrong with my code.
welcome;
In your HTML code, <a href="projectnew" class="projectbutton"> you have an href for your a element, if you click on this, it will go to the page "www.yourdomain.com/projectnew" since this page does not exist, you will be redirected to your error page...
To solve this problem, you should use preventDefault, in order to prevent your link element to operate things that you do not want.
$('a.projectbutton').click(function(event) {
event.preventDefault();
var page = $(this).attr('href');
$('#content').fadeOut(400);
setTimeout(function(){$('#content').load('views/' + page + '.html')}, 400);
$('#content').fadeIn(400);
return false;
});
I did not try it out, but it should work.
Read more about preventDefault: https://api.jquery.com/event.preventdefault/
OR;
Since the main problem is your href attributes in your a elements, try to remove them;
Home
Use title as your specifier in your JS;
$('a.projectbutton').click(function() {
var page = $(this).attr('title'); //changed this into title.
$('#content').fadeOut(400);
setTimeout(function(){$('#content').load('views/' + page + '.html')}, 400);
$('#content').fadeIn(400);
return false;
});

Why are images duplicated with append()?

When a "project" is clicked, I want multiple images to be appended to a container element.
Projects and their image URLs are defined in a JavaScript object.
If I click a project, its images are correctly appended. But if I close the project viewer and click that project again, the images are all duplicated. I think this has something to do with append().
What am I doing wrong?
I made a demonstration below:
$(function() {
var projects = {
'project_1': {
'title': 'EduTravel For Credit',
'description': 'Innovative travel for credit.',
'images': [
'http://lorempixel.com/400/30/abstract/1/',
'http://lorempixel.com/400/30/abstract/2/'
]
}
}
var projectData = projects["project_1"];
jQuery('button').on('click', function() {
$.each(projectData.images, function(item) {
$('#project-images').append('<span class="image_holder" style="background-image:url(' + projectData.images[item] + ');"></span>')
});
$('#project_images').html('');
});
});
.image_holder {
display: block;
height: 30px;
background-size: cover;
margin: 0 0 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>CLICK ME</button>
<div id="project-images"></div>
View the live website
From the source code on your website, it seems that you might be attempting to remove images from the container before appending new images:
$('#project_images').html('');
However, that selector uses an underscore while the actual element uses a hyphen:
<div id="project-images">
Also, you are clearing the contents after appending images rather than before.
I suggest using jQuery's empty() on the container before appending new images:
$(function() {
var projects = {
'project_1': {
'images': [
'http://lorempixel.com/400/30/abstract/1/',
'http://lorempixel.com/400/30/abstract/2/'
]
},
'project_2': {
'images': [
'http://lorempixel.com/400/30/abstract/3/',
'http://lorempixel.com/400/30/abstract/4/'
]
},
'project_3': {
'images': [
'http://lorempixel.com/400/30/abstract/5/',
'http://lorempixel.com/400/30/abstract/6/'
]
}
}
var projectData = projects["project_1"];
jQuery('button').on('click', function() {
var id=jQuery(this).data('id'),
projectData=projects["project_"+id];
$('#project-images').empty();
$.each(projectData.images, function(item) {
$('#project-images').append('<span class="image_holder" style="background-image:url(' + projectData.images[item] + ');"></span>')
});
});
});
.image_holder {
display: block;
height: 30px;
background-size: cover;
margin: 0 0 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button data-id="1">LOAD #1</button>
<button data-id="2">LOAD #2</button>
<button data-id="3">LOAD #3</button>
<div id="project-images"></div>
An alternate method is to concatenate a string of new images, and then set the HTML of the container without using append():
$(function() {
var projects = {
'project_1': {
'images': [
'http://lorempixel.com/400/30/abstract/1/',
'http://lorempixel.com/400/30/abstract/2/'
]
},
'project_2': {
'images': [
'http://lorempixel.com/400/30/abstract/3/',
'http://lorempixel.com/400/30/abstract/4/'
]
},
'project_3': {
'images': [
'http://lorempixel.com/400/30/abstract/5/',
'http://lorempixel.com/400/30/abstract/6/'
]
}
}
var projectData = projects["project_1"];
jQuery('button').on('click', function() {
var id=jQuery(this).data('id'),
projectData=projects["project_"+id],
html_string='';
$.each(projectData.images, function(item) {
html_string+='<span class="image_holder" style="background-image:url(' + projectData.images[item] + ');"></span>';
});
$('#project-images').html(html_string);
});
});
.image_holder {
display: block;
height: 30px;
background-size: cover;
margin: 0 0 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button data-id="1">LOAD #1</button>
<button data-id="2">LOAD #2</button>
<button data-id="3">LOAD #3</button>
<div id="project-images"></div>

I created a sorting tool with Angular.js. How can I animate ng-click to create animated transitions when the items are sorted?

I am building a personal portfolio site with Angular and decided to build my project sorter using pure Angular, instead of doing it with jQuery. I utilized the filter feature of Angular, and am able to get the projects to sort correctly. However, when I'm going through the ng-animate section, there's no support for ng-click and filters that I can see. I was also not able to get the ng-animate to work on the ng-repeat (when the projects are all displayed.) I basically want cool transitions whenever a new filter is selected. The same type of reactions to clicking a button as what happens here.
https://mixitup.kunkalabs.com/
What would be the best course of action to handle animating those types of things? Also, does my code look properly done the 'Angular' way?
jsfiddle-
http://jsfiddle.net/jtbitt/tg6oh0g1/6/
HTML -
<div id="portfolio" ng-controller="mainController as main">
<div class="container">
<div class="row">
<div>Portfolio</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="">
<ul ng-repeat="language in main.languages">
<li><button ng-click="main.projectSort(language)">{{ language.name }}</button></li>
</ul>
</div>
</div>
</div>
<div class="row">
<div ng-repeat="project in main.projectsToShow">
<div class="portfolio-projects language-{{ project.reference }}">{{ project.name }}</div>
</div>
</div>
</div>
</div>
CSS -
#portfolio {
height: 100%;
width: 100%;
font-color: black;
}
#portfolio .container, #portfolio .container .row {
height: 100%;
width: 100%;
}
#portfolio .container .row {
height: 33.3%;
}
.portfolio-projects{
border-style: solid;
border-color: #000000;
padding: 10px;
margin: 10px;
}
.language-angular {
color: blue;
}
.language-ruby {
color: red;
}
.language-node {
color: green;
}
JS -
var app = angular.module('portfolioSorter', []);
app.controller('mainController', ['filterFilter', function(filterFilter) {
var vm = this;
vm.languages = [
{
name: 'ALL',
reference: 'all'
},
{
name: 'ANGULAR',
reference: 'angular'
},
{
name: 'NODE',
reference: 'node'
},
{
name: 'RUBY ON RAILS',
reference: 'ruby'
}
];
vm.projects = [
{
name: 'Tic-Tac-Toe',
language: 'ANGULAR.JS',
reference: 'angular'
},
{
name: 'Escrow',
language: 'RUBY ON RAILS',
reference: 'ruby'
},
{
name: 'Feed.Me',
language: 'RUBY ON RAILS',
reference: 'ruby'
},
{
name: 'Gone-In',
language: 'NODE.JS',
reference: 'node'
}
];
vm.projectsToShow = vm.projects;
vm.projectSort = function(language) {
vm.projectsToShow = vm.projects;
switch (language.reference) {
case 'all':
vm.projectsToShow;
break;
case 'angular':
vm.projectsToShow = filterFilter(vm.projectsToShow, 'angular');
break;
case 'node':
vm.projectsToShow = filterFilter(vm.projectsToShow, 'node');
break;
case 'ruby':
vm.projectsToShow = filterFilter(vm.projectsToShow, 'ruby');
break;
default:
vm.projectsToShow;
};
};
}]);

Categories

Resources