Closed eliottenos closed 7 years ago
Share your index.html file
Share your index.js file
Share the file that addHandlers
is defined in
@MicFin index.html
<!DOCTYPE html>
<html>
<head>
<title>Map</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Do not add `link` tags unless you know what you are doing -->
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
<!-- Do not add `script` tags unless you know what you are doing -->
<script src="public/vendor.js" type="text/javascript" charset="utf-8" defer></script>
<script src="public/application.js" type="text/javascript" charset="utf-8" defer></script>
</head>
<body class="container-fluid">
<nav class="navbar navbar-default navbar-div" role="navigation"></nav>
<div class="container wrapper-div">
<div class="content-div"></div>
<!-- <div class="content-div2"></div> -->
<!-- temporary forms for front end testing -->
<div class="temp-div"></div>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js"></script>
<script src="node_modules/datamaps/dist/datamaps.world.min.js"></script>
<div class="map" id="container" style="position: relative; width: 1000px; height: 600px;"></div>
<!-- <script>
var map = new Datamap({element: document.getElementById('container')});
</script> -->
<script type="text/javascript">
</script>
<script>
const map = new Datamap({
element: document.getElementById('container'),
done: function(datamap) {
datamap.svg.selectAll('.datamaps-subunit').on('click', function(geography) {
alert(geography.properties.name);
})
}
})
</script>
<div class="content-div2"></div>
</body>
</html>
index.js
const setAPIOrigin = require('../../lib/set-api-origin')
const config = require('./config')
const view = require('./view')
const authEvents = require('./auth/events')
const locationEvents = require('./locations/events')
// const CSSMap = require('cssmap-europe/cssmap-europe.css')
$(() => {
setAPIOrigin(location, config)
view.initView()
authEvents.addHandlers()
locationEvents.addHandlers()
}
)
// use require with a reference to bundle the file and use it in this file
// const example = require('./example')
// use require without a reference to ensure a file is bundled
require('./example')
addHandlers is in view.js
// const store = require('./store')
// initializes view containers and event handlers
const initView = () => {
// render private view to navbar-div
renderView('.navbar-div', 'nav-public')
// console.log('hit render view')
// user sign up / sign in forms
renderView('.content-div', 'form-auth')
$('.map').hide()
// add event handlers for view contoller elements
addHandlers()
}
//
// VIEW RENDERING FUNCTIONS
//
// renderView(element, hbsFile, params)
// renders the template and replaces the element
const renderView = (element, hbsFile, params) => {
const template = require(`./templates/${hbsFile}.handlebars`)
const content = template(params)
$(element).html(content)
}
// replaceView(element, hbsFile, params)
// renders the template and replaces the element
const replaceView = (element, hbsFile, params) => {
const template = require(`./templates/${hbsFile}.handlebars`)
const content = template(params)
$(element).replaceWith(content)
}
// appendView(element, filepath, params)
// renders the template and appends it to the element
const appendView = (element, hbsFile, params) => {
const template = require(`./templates/${hbsFile}.handlebars`)
const content = template(params)
$(element).append(content)
}
// prependView(element, filepath, params)
// renders the template and appends it to the element
const prependView = (element, hbsFile, params) => {
const template = require(`./templates/${hbsFile}.handlebars`)
const content = template(params)
$(element).prepend(content)
}
// clearView(element)
// clears the html from the specified element
const clearView = (element) => {
$(element).html('')
}
//
// PUBLIC AND PRIVATE MODES
//
// setPublicMode()
// set public mode for navbar and content area
const setPublicMode = () => {
// closeAlert()
renderView('.navbar-div', 'nav-public')
renderView('.content-div', 'form-auth')
clearView('.temp-div')
}
const setPrivateMode = () => {
// closeAlert()
renderView('.navbar-div', 'nav-private')
// renderView('.content-div', 'map')
renderView('.content-div2', 'locations')
$('.map').show()
// $('.form-auth').hide()
}
//
// VALIDATION & ALERT METHODS
//
// formAlert(form, field)
// triggers form input validation alert
const formAlert = (form, field) => {
clearFormAlerts(form)
// apply alert classes to specfic input
$(field).closest('.form-group').addClass('has-warning has-feedback')
// add alert icon to specific input
$(field).closest('.input-group').find('.form-control').after(`<span class="glyphicon glyphicon-warning-sign form-control-feedback"></span>`)
// show help text for specific input
$(field).closest('.form-group').find('.help-block').show()
}
// clearFormFields(form)
// clear all values from form fields
const clearForm = (form) => {
// clear form field alerts
clearFormAlerts(form)
// clear field values
$(form).find('.form-control').val('')
}
// clearFormAlerts(form)
// clear all feedback classes and icons from form fields
const clearFormAlerts = (form) => {
// clear all alert classes from inputs
$(form).find('.form-group').removeClass('has-warning has-feedback')
// remove all alert class icons from inputs
$(form).find('.form-group .form-control-feedback').remove()
// hide any visible help text
$(form).find('.help-block').hide()
}
// showAlert(mode, message)
// displays global alert box for info or warning
const showAlert = (mode, message) => {
// convert mode label to bootstrap class
mode = (mode === 'error') ? 'danger' : 'info'
// if there's already an alert
if ($('.alert').length) {
// replace the existing alert
replaceView('.alert', 'alert', { mode: mode, message: message })
} else {
// insert a new alert
prependView('.content-div', 'alert', { mode: mode, message: message })
}
}
// closeError()
// close global error box but not info alerts
const closeError = () => {
$('.alert-danger').alert('close')
}
// closeAlert()
// close all global alert boxes
const closeAlert = () => {
$('.alert').alert('close')
}
// showChangePasswordSuccess()
// password changed successfully
const showChangePasswordSuccess = () => {
// collapse change password dropdown
$('#change-password-nav').dropdown('toggle')
$('.navbar-collapse').collapse('hide')
// clear change password form fields
$('#change-password input').val('')
// display successful alert message
showAlert('info', 'Your password is changed. Hope you remember it.')
}
// showChangePasswordFailure()
// password change failed
const showChangePasswordFailure = () => {
// collapse change password dropdown
$('#change-password-nav').dropdown('toggle')
$('.navbar-collapse').collapse('hide')
// clear change password form fields
$('#change-password input').val('')
// display successful alert message
showAlert(`error`, `For highly complex reasons, your password couldn't be changed.`)
}
const addHandlers = () => {
// DROPDOWN MENU EVENTS
// add animation to dropdown expand
$('.navbar-div').on('show.bs.dropdown', '.dropdown', (event) => {
$(event.target).find('.dropdown-menu').first().stop(true, true).slideDown(250)
})
// add animation to dropdown collapse
$('.navbar-div').on('hide.bs.dropdown', '.dropdown', (event) => {
event.preventDefault()
$(event.target).find('.dropdown-menu').first().stop(true, true).slideUp(
250, () => {
// close dropdown menu
$('.dropdown').removeClass('open')
$('.dropdown').find('.dropdown-toggle').attr('aria-expanded', 'false')
// clear fields
clearForm($(event.target).find('.form').val('id'))
})
})
}
module.exports = {
initView,
setPublicMode,
setPrivateMode,
showAlert,
formAlert,
clearForm,
clearFormAlerts,
closeError,
closeAlert,
showChangePasswordSuccess,
showChangePasswordFailure,
appendView
}
Is there a reason why <!-- <div class="content-div2"></div> -->
is commented out?
Your click handler is applied to an element with class content-div2
$('.content-div2').on('submit', '.location-update', onUpdateLocation)
yep, ive used it somewhere else but cant find it right now. If I uncomment it renders twice
ahhhh, its at the bottom of index.html
Where is the element with the class location-update
?
$('.content-div2').on('submit', '.location-update', onUpdateLocation)
in get-locations.handlebar
{{#each locations as |location|}}
<h3>
Location:
</h3>
<h4>
{{ location.country }}
</h4>
<h4>
{{ location.note }}
</h4>
<button id="delete-{{ location.id }}" type="button" class="delete-location">Delete Location</button>
<p>Update Location Notes:</p>
<form class='location-update' id='update-{{ location.id }}'>
<div class="form-group">
<input type="text" name="place[note]"placeholder="Note">
<input type="submit" name="submit" value="Submit">
</form>
{{/each}}
I feel like its a problem with my function in events.js or how im sending the ajax call? @MicFin
Why are there 2 addHandlers
functions?
The addHandlers
function that is called in the index.js
is from the view.js
:
// addHandlers is in view.js
const addHandlers = () => {
// DROPDOWN MENU EVENTS
// add animation to dropdown expand
$('.navbar-div').on('show.bs.dropdown', '.dropdown', (event) => {
$(event.target).find('.dropdown-menu').first().stop(true, true).slideDown(250)
})
// add animation to dropdown collapse
$('.navbar-div').on('hide.bs.dropdown', '.dropdown', (event) => {
event.preventDefault()
$(event.target).find('.dropdown-menu').first().stop(true, true).slideUp(
250, () => {
// close dropdown menu
$('.dropdown').removeClass('open')
$('.dropdown').find('.dropdown-toggle').attr('aria-expanded', 'false')
// clear fields
clearForm($(event.target).find('.form').val('id'))
})
})
}
But there is another function addHandlers
that actually has the form event we want, what file is that in?
const addHandlers = () => {
$('.content-div2').on('submit', '#location-create', onCreateLocation)
$('.content-div2').on('submit', '.location-update', onUpdateLocation)
// $('.content-div2').on('click', '#location-country-delete', onDeleteLocation)
$('.content-div2').on('click', '.delete-location', onDeleteLocation)
$('.content-div2').on('click', '#location-get', onGetAllLocations)
}
thats in locations/events.js its required in index.js
const locationEvents = require('./locations/events')
and called with
locationEvents.addHandlers()
Can you share all of ./locations/events.js
?
const getFormFields = require(`../../../lib/get-form-fields`)
// const locationListing = require('../templates/locations.handlebars')
const api = require('./api')
const ui = require('./ui')
const onCreateLocation = function (event) {
const data = getFormFields(event.target)
event.preventDefault()
api.createLocation(data)
.then(ui.createLocationSuccess)
.catch(ui.createLocationFailure)
}
const onGetAllLocations = function () {
api.getLocation('')
.then(ui.getLocationSuccess)
.catch(ui.getLocationError)
// } else {
// console.log('Please provide a location id!')
}
// const onUpdateLocation = function (event) {
// event.preventDefault()
// // console.log('inside of onUpdateLocation')
// const data = getFormFields(event.target)
// api.updateLocation(data)
// .then(ui.updateLocationSuccess)
// .catch(ui.updateLocationFailure)
// // }
// }
const onUpdateLocation = function (event) {
event.preventDefault()
// const place = event.target
const data = getFormFields(event.target)
const index = event.target.id.indexOf('-')
const updateLocation = event.target.id.slice(index + 1)
console.log('id here', updateLocation)
api.updateLocation(updateLocation, data)
.then(ui.updateLocationSuccess)
.catch(ui.updateLocationFailure)
// } else {
// console.log('Please provide a location id!')
}
const onDeleteLocation = function (event) {
// event.preventDefault()
// const place = event.target
const index = event.target.id.indexOf('-')
const deleteLocation = event.target.id.slice(index + 1)
console.log('id here', deleteLocation)
api.deleteLocation(deleteLocation)
.then(ui.deleteLocationSuccess)
.catch(ui.deleteLocationFailure)
// } else {
// console.log('Please provide a location id!')
}
const addHandlers = () => {
$('.content-div2').on('submit', '#location-create', onCreateLocation)
$('.content-div2').on('submit', '.location-update', onUpdateLocation)
// $('.content-div2').on('click', '#location-country-delete', onDeleteLocation)
$('.content-div2').on('click', '.delete-location', onDeleteLocation)
$('.content-div2').on('click', '#location-get', onGetAllLocations)
}
module.exports = {
addHandlers
}
Add the following alerts
and let me know which ones pop up. We are using alert
instead of console.log
because your page is reloading so it may reload before we can check what is logged but each alert will be seen immediately when triggered.
// index.js
$(() => {
setAPIOrigin(location, config)
view.initView()
authEvents.addHandlers()
alert('index.js file')
locationEvents.addHandlers()
})
// location/events.js
const addHandlers = () => {
$('.content-div2').on('submit', '#location-create', onCreateLocation)
alert("events.js file")
$('.content-div2').on('submit', '.location-update', onUpdateLocation)
// $('.content-div2').on('click', '#location-country-delete', onDeleteLocation)
$('.content-div2').on('click', '.delete-location', onDeleteLocation)
$('.content-div2').on('click', '#location-get', onGetAllLocations)
}
const onUpdateLocation = function (event) {
event.preventDefault()
alert("onUpdateLocation")
const data = getFormFields(event.target)
const index = event.target.id.indexOf('-')
const updateLocation = event.target.id.slice(index + 1)
console.log('id here', updateLocation)
api.updateLocation(updateLocation, data)
.then(ui.updateLocationSuccess)
.catch(ui.updateLocationFailure)
// } else {
// console.log('Please provide a location id!')
}
it hits index.js and events.js but not onUpdateLocation
The HTML in this Handlebars template has a <div>
that needs to be closed before the <form
> closes.
<form class='location-update' id='update-{{ location.id }}'>
<div class="form-group">
<input type="text" name="place[note]"placeholder="Note">
<input type="submit" name="submit" value="Submit">
</form>
oh yeah, still getting the same response, not hitting onUpdateLocation
Delegated events have to be on a parent element for a child element's event.
$('.content-div2').on('submit', '.location-update', onUpdateLocation)
The element with the class content-div2
has to be a parent element of your form with class location-update
. Is that the case?
<div class="content-div2"></div>
is just an empty div in index.html where to render content
Does it ever get removed or replaced in the DOM?
Let's try changing $('.content-div2').on('submit', '.location-update', onUpdateLocation)
to:
$('body').on('submit', '.location-update', onUpdateLocation)
its used in view.js is all I can think?
const setPrivateMode = () => {
// closeAlert()
renderView('.navbar-div', 'nav-private')
// renderView('.content-div', 'map')
renderView('.content-div2', 'locations')
$('.map').show()
clearView('.content-div', 'form-auth')
// $('.form-auth').hide()
}
is that applicable?
What results did this give you?
$('body').on('submit', '.location-update', onUpdateLocation)
the same result, only hitting index.js and events.js alerts I've pushed what I have to master branch if thats easier to look at https://github.com/eliottenos/capstone-client
Last bit of debugging I can do for the night.
Check the value of the callback you are passing.
Check the jQuery selector you are using.
const addHandlers = () => {
$('.content-div2').on('submit', '#location-create', onCreateLocation)
console.log("onupdate is ", onUpdateLocation)
console.log("content div is ", $('.content-div2'))
// comment out the event so the page doesn't reload on submit
// $('.content-div2').on('submit', '.location-update', onUpdateLocation)
// $('.content-div2').on('click', '#location-country-delete', onDeleteLocation)
$('.content-div2').on('click', '.delete-location', onDeleteLocation)
$('.content-div2').on('click', '#location-get', onGetAllLocations)
}
Previously I said:
Delegated events have to be on a parent element for a child element's event. $('.content-div2').on('submit', '.location-update', onUpdateLocation) The element with the class content-div2 has to be a parent element of your form with class location-update. Is that the case?
It looks like you are adding the template with the form here:
const getLocationSuccess = (data) => {
$('.createSuccess').empty()
// console.log('this one', data)
// console.log($(data))
let locations = showLocationTemplate({ locations: data.places })
$('.getBlank1').append(locations)
}
And appending it to the element with getBlank1
that is in the locations.handlebars
template but when is the locations.handlebars
template added to the DOM? It looks commented out in locations/ui.js
and not added to the DOM.
Additionally, you have a couple other javascript files from a library mixed in there, if they are adding events to the form that would also be problematic. Don't stay up all night on this.
great, will look into it, thanks Mike
Im trying to update the notes attribute using handlebars but the page just refreshes on submit, not hitting the server. Im trying to use the same slice method to get the data id and then getFormField to get the updated not
Any suggestions?