I'm using the AniList API to make some requests and load the data.
The first request I'm doing it works well (note that the page loads with some covers), but when I'm using the search button I get failed to fetch. Because the first time worked, but not when modifying the query, I thought that might be wrong in the way I was modifying it, but after a double check, I only modify variables.search and then I proceed to do the same as the first time I'm loading the page, so I don't really know why it's failing. I also tried to modify the first query, when the page is loading, and it works, so I don't think it has anything to do with the API.
Here's the code
const resultsEl = document.getElementById("container-results");
const submitBtnEl = document.getElementById("submit-button");
const inputTxtEl = document.getElementById("input-txt")
var query = `
query ($id: Int, $page: Int, $perPage: Int, $search: String) {
Page (page: $page, perPage: $perPage) {
pageInfo {
total
currentPage
lastPage
hasNextPage
perPage
}
media (id: $id, search: $search) {
id
title {
romaji,
english,
}
type
coverImage {
large
}
}
}
}
`;
var variables = {
search: "Pokemon",
page: 1,
perPage: 5000
};
var url = 'https://graphql.anilist.co',
options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
query: query,
variables: variables
})
};
fetch(url, options).then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response) {
return response.json().then(function (json) {
return response.ok ? json : Promise.reject(json);
});
}
function handleData(data) {
processData(data);
}
function handleError(error) {
console.error(error);
alert('Error, check console');
}
function processData(data) {
let processedData = [];
queryResults = data.data.Page.media;
for (let i = 0; i < queryResults.length; i++) {
let obj = {}
obj.title = queryResults[i].title.romaji;
obj.image = queryResults[i].coverImage.large;
processedData.push(obj);
}
for (let i = 0; i < processedData.length; i++) {
let img_div = document.createElement("div");
img_div.className = "cover-Image"
img_div.innerHTML += processedData[i].title;
img_div.innerHTML += "<img width=250 height=400 src=" + processedData[i].image + ">";
resultsEl.appendChild(img_div);
}
}
submitBtnEl.addEventListener("click", () => {
const userQuery = inputTxtEl.value;
if (userQuery !== "") {
variables.search = userQuery;
options.body = JSON.stringify({
query: query,
variables: variables
})
fetch(url, options).then(handleResponse)
.then(handleData)
.catch(handleError);
}
else {
resultsEl.innerHTML = "";
}
})
* {
box-sizing: border-box;
margin: 0;
padding: 0;
background-color: black;
}
body {
background-color: black;
}
.container-results {
display:flex;
flex-wrap: wrap;
justify-content: center;
}
.cover-Image{
padding: .3em;
margin: .1em;
width:300px;
color:white;
}
img{
margin: 0.5em;
}
#media (min-width: 960px) {
#nani{
width: 500px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Working with api's example</title>
<!--Bootstrap related things-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<link rel="stylesheet" href="css/styles.css">
<script src="js/script.js" defer></script>
</head>
<body>
<!--NAVBAR-->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Manga search</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<form class="form-inline my-2 my-lg-0 mx-auto">
<input class="form-control mr-sm-2" id="input-txt" type="search" placeholder="Place title" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" id="submit-button" type="submit">Search</button>
</form>
</div>
</nav>
<!--RESULTS-->
<div class="container-fluid">
<div class="container-results" id="container-results"> </div>
</div>
</body>
</html>
Vishal is correct. This is throwing an error because you are navigating away from the page when they submit.
Change your event listener to start like this and the problem goes away:
submitBtnEl.addEventListener("click", e => {
e.preventDefault();
When the user navigates away, the request is aborted, thus the error handler fires.
You can see this in action (before you fix it as above) by looking at the network tab. The request shows "cancelled", i.e. the browser cancelled the request.
It's a little confusing here, because the order of events is:
User clicks the submit button
The event listener you created runs
Inside of it, your fetch fires, including the establishment of its error handler
When your event listener finishes, the default event handler runs. Since this is a form, and the button was a 'submit' type, the default event handler is to submit the form. When no action URL is given, it presumes the handler is the same page.
The browser begins the process of navigating (i.e. submitting) to the same page.
The browser cancels the fetch request, since the user is navigating "away" from the current page.
The fetch request, having been cancelled, has now errored, and thus the error handler fires
Your alert runs inside the error handler, pausing the execution of the page, including the navigation
So at that point it seems like they haven't navigated yet, but the process has already started enough to have cancelled the request.
Related
My page keeps on reloading after my fetch request is complete. I don't want the page to reload after I submit the form. Can anyone help out as to why even after using e.preventDefault() I get that behavior? Also can you suggest better formatting tips for JS as I'm a beginner and would like your input. I'm fetching the data from a fake REST API made using json-live-server
HTML
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<title>Document</title>
</head>
<body class="body">
<h1> Vaccination Centers</h1>
<div id='app'>
<form id='form'>
<input type="text" id='enrollment' />
<input type='text' id='session' />
<button type="submit">submit</button>
</form>
</div>
<script type="module" src="main.js"></script>
</body>
</html>
JS
let listArray
function getCenters () {
fetch ('http://localhost:3001/students')
.then(
response => response.json()
)
.then(data => {
listArray = data
console.log(listArray)
})
};
function init () {
getCenters()
const form = document.getElementById('form')
form.addEventListener('submit', (e) => validate(e))
}
function validate (e) {
console.log(e)
e.preventDefault()
let enrollment = document.getElementById('enrollment').value
let student = listArray.find(s => s.enrollment.toString() === enrollment.toString())
fetch ('http://localhost:3001/students/' + student.id, {
method: 'PATCH',
headers: {
'Content-type': 'application/json; charset=UTF-8' // Indicates the content
},
body: JSON.stringify({ paidFee: true })
}).then(document.getElementById('app').innerHTML = 'HELLO BITCHES')
}
window.onload = init
We can all agree that e.preventDefault() placed at the first line ⃰ in the event handler (aka validate(e)) will stop the default browser behavior of a <form> when a "submit" event is triggered on it. The behavior OP is observing is the destructive overwriting of the following:
.then(document.getElementById('app').innerHTML = 'HELLO BITCHES')
Just remove the above and you shouldn't have what appears as a page reload, but if you must say, "HELLO" to the bitches, use .insertAdjacentHTML() instead:
.then(document.getElementBYId('app').insertAdjacentHTML('beforeBegin', 'HELLO BITCHES'))
The following example has an event handler for the "submit" (submitter(e)) and "click" (clicker(e)) events. If button#A is clicked, .innerHTML is used and if button#B is clicked, .insertAdjacentHTML() is used. There is also a logger function (eventLogger(e)) which will log:
type of event........................................e.type
event listener #id............................e.currentTarget
button #id..........................................e.target.id (from 'click' event)
if default was prevented or not.....e.defaultPrevented
⃰actually it's console.log() at that position but there's no difference in this context
Best viewed in Full Page mode
document.forms[0].addEventListener('submit', submitter);
document.querySelectorAll('button').forEach(node => node.addEventListener('click', clicker));
function submitter(e) {
e.preventDefault();
let ID = this.elements.AB.value;
const APP = document.getElementById('app');
switch (ID) {
case 'A':
APP.innerHTML = 'HELLO BITCHES - #app is gutted by .innerHTML - everything within #app is overwritten';
break;
case 'B':
const htmlString = 'HELLO BITCHES - this is added in front of #app - nothing is overwritten bitches';
APP.insertAdjacentHTML('beforeBegin', htmlString);
break;
default:
break;
}
eventLogger(e);
};
function clicker(e) {
document.forms[0].AB.value = e.target.id;
};
function eventLogger(e) {
let ID = e.target.elements.AB.value;
console.clear()
let log = 'Event Type: ' + e.type + '\nEvent Listener ID: ' + e.currentTarget.id + '\nButton ID: ' + ID + '\nDefault Prevented: ' + e.defaultPrevented;
console.log(log);
};
body {
padding: 8px;
font: 1ch/1 Consolas;
}
h1 {
font-size: 1.75ch/1;
}
#app {
margin: 8px;
padding: 20px;
outline: 3px dashed blue;
}
form {
padding: 20px;
outline: 3px dotted red
}
input {
display: inline-block;
width: 15ch;
}
button {
display: inline-block;
width: 6ch;
cursor: pointer;
}
p {
display: inline-block;
}
p:first-of-type {
color: blue;
}
p:last-of-type {
color: red;
}
code {
font-weight: bold;
color: #ab00ef;
}
/* SO Console Display - Right Side Column */
.as-console-wrapper {
width: 50% !important;
max-height: 100%;
margin: 0 0 25% 50%;
font-size: 0.8ch/1;
font-variant: normal;
}
.as-console-row.as-console-row::after {
content: '';
padding: 0;
margin: 0;
border: 0;
width: 0;
}
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body class="body">
<h1>Vaccination Centers</h1>
<p>Blue dashed outline is <code>#app</code></p>
<p>Red dotted outline is <code>#form</code></p><br>
<div id='app'>
<form id='form'>
<input type="text" id='enrollment'>
<input type='text' id='session'>
<button id='A'>A</button>
<button id='B'>B</button>
<input id='AB' type='hidden'>
</form>
</div>
</body>
</html>
There were a few bits that needed some attendence:
In your original script you used an asynchronous fetch to define the variable listArray. Unfortunately you did not wait for the value to be put into that variable but continued straight away. This "awaiting" can only happen in an asynchronous function. Therefore:
I created an async function as this makes it much easier to process promises with await inside.
The first one fills listArray with all the registered students for comparison with an entered name
The comparison needs to be done on enrollment.value.trim().toLowerCase() (there is no .toString() involved)
If the name was found, a second fetch() command is sent, "PATCHing" the new information to the server
The return data from the server is then displayed in JSON format under the "success message".
const api='http://jsonplaceholder.typicode.com/users/';
document.getElementById('form').addEventListener("submit",validate);
async function validate(e) {
e.preventDefault();
const listArray=await fetch(api).then(r=>r.json());
let student= listArray.find(s=>s.username.toLowerCase()===enrollment.value.trim().toLowerCase())
if (student) {
const d = await fetch(api+student.id, {method: 'PATCH',headers: {'Content-Type': 'application/json'},body: JSON.stringify({paidFee:true})}).then(r=>r.json());
document.getElementById('app').innerHTML = '<div>HELLO BITCHES</div><pre>'+JSON.stringify(d,null,2)+'</pre>';
} else console.log("This student does not exist in our list: "+listArray.map(s=>s.username).join(" "));
}
<h1> Vaccination Centers</h1>
<div id='app'>
<form id='form'>
<input type="text" id='enrollment' value="Bret">
<input type='text' id='session'>
<button type="submit">submit</button>
</form>
</div>
I am trying to get some data from the GitHub API using jQuery(AJAX), and appending it in a static webpage. Below are my HTML and JS snippets.
$(document).ready(function(){
$.ajax({
url: 'https://api.github.com/repos/FearlessPython/Basics-of-Python',
}).done(function(repo){
$('#heading').html(`${repo.name}<hr>`);
$('#stats').html(`
<strong>Stars</strong>: ${repo.stargazers_count} <br>
<strong>Watchers</strong>: ${repo.watchers_count} <br>
<strong>Language</strong>: ${repo.language} <br>
<strong>Open Issues</strong>: ${repo.open_issues_count} <br>
<strong>License</strong>: ${repo.license.name}<br>
`);
});
$.ajax({
method: "GET",
url: "https://api.github.com/repos/FearlessPython/Basics-of-Python/contributors",
dataType: "json"
}).done(function(data){
$.each(data, function(index, url){
$.ajax({
url: data[index].url
}).done(function(individual_contributor){
// console.log(data[index].url);
$('ul#users').append(`
<li><strong>${individual_contributor.name}</strong></li>
<li><strong>Bio:</strong> ${individual_contributor.bio}</li>
<li><strong>Public Repos:</strong> ${individual_contributor.public_repos}</li>
<li><strong>Followers:</strong> ${individual_contributor.followers}</li>
<li><strong>Following:</strong> ${individual_contributor.following}</li>
`)
});
});
$.map(data, function(contributor, i){
// contrb.push(contributor);
$('ol#contributors').append(`
<li>${contributor.login}</li>
<img src = "${contributor.avatar_url}" style = "float: right;" width=10%>
<ul id="users"></ul>
`);
});
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
</head>
<body>Here, dynamic statistics are available regarding this repository in GitHub.
<div id="statistics">
<h3 id="heading"></h3>
<ul id="stats"></ul>
<h4>Contributors</h4><hr>
<ol id="contributors">
<!-- <ul id="users"></ul> -->
</ol>
</div>
</body>
</html>
You can see that under each user, the same thing iterates again and again. Using .html() instead of .append() overwrites the first iteration data and everything gets replaced by the latest iteration's data. The ideal result should be like this:
I also tried to use for loop, but the same thing is happening. I am trying to solve it from the last few days, but unable to solve it. I have just started using jQuery and AJAX.
Note: In case if the GitHub API requests exceed for you, then you won't be able to see the result of the above code snippets. So I am also including an image of the current situation of the Webpage.
After you get the contributor list you're performing two iterations. The $.each,
in which you fire a request to get the contributor details, which will be appended to a container with id='users'. (That doesn't exist yet!)
$.each(data, function(index, url){
// request contributor details
}
and the $.map which appends the login and avatar to a list but also a container <ul id='users'>.
$.map(data, function(contributor, i){
$('ol#contributors').append(`
<li>${contributor.login}</li>
<img src = "${contributor.avatar_url}" style = "float: right;" width=10%>
<ul id="users"></ul>` // this will cause you trouble
);
});
Now, ids should be unique within the document, so appending extra elements with the same id won't work as expected.
See, you have a racing condition in which your contributor details handler depends on an element that you haven't created yet. Anyway, when it resolves, its contents will be appended to whatever element is found when looking for $('#users'), most probably the first one in the DOM.
Rounding up:
perform just one iteration over the contributor list
append the contributor details to the corresponding user <ul>
don't use ids for a container you mean to repeat across a list (or at least compute its id instead of hardcoding it)
When you get the list, I would iterate using for..of. then on each loop I'd declare the <ul> element (which becomes block scoped) and use that reference to append the user details when the child request resolves.
for (let contributor of contributors) {
// block scoped
let userDetailsElement = $('<ul class="users"></ul>');
$('ol#contributors')
.append(userHeader(contributor))
.append(userDetailsElement);
$.getJSON(contributor.url)
.then( individual_contributor => {
// I know which <ul> I'm appending to
userDetailsElement.append(
contributorDetailsHtml(individual_contributor)
);
});
}
In the following snippet I'm declaring jQuery's callback as async, therefore I could also await the contributor details just like
let individual_contributor = await $.getJSON(contributor.url);
userDetailsElement.append(
contributorDetailsHtml(individual_contributor)
);
awaiting on each user's detail means that requests will be ran sequentially, whereas firing a thenable request will do it in parallel. If you were about to query a repo with hundreds of contributors the choice can make a difference not just because of performance but also because you will get throttled and a part of your dom won't render.
const repoUrl = 'https://api.github.com/repos/FearlessPython/Basics-of-Python';
function repoStatsHtml(repo) {
return `
<strong>Stars</strong>: ${repo.stargazers_count} <br>
<strong>Watchers</strong>: ${repo.watchers_count} <br>
<strong>Language</strong>: ${repo.language} <br>
<strong>Open Issues</strong>: ${repo.open_issues_count} <br>
<strong>License</strong>: ${repo.license.name}<br>
`;
}
function contributorDetailsHtml(individual_contributor) {
return `
<li><strong>${individual_contributor.name}</strong></li>
<li><strong>Bio:</strong> ${individual_contributor.bio}</li>
<li><strong>Public Repos:</strong> ${individual_contributor.public_repos}</li>
<li><strong>Followers:</strong> ${individual_contributor.followers}</li>
<li><strong>Following:</strong> ${individual_contributor.following}</li>
`;
}
function userHeaderHtml(contributor) {
return `
<li>${contributor.login}</li>
<img src = "${contributor.avatar_url}" class="avatar">
`;
}
$(document).ready(async function() {
$.getJSON(repoUrl).done(function(repo) {
$('#heading').html(`${repo.name}<hr>`);
$('#stats').html(repoStatsHtml(repo));
});
let contributors = await $.getJSON(`${repoUrl}/contributors`);
for (let contributor of contributors) {
let userDetailsElement = $('<ul class="users"></ul>');
$('ol#contributors')
.append(userHeaderHtml(contributor))
.append(userDetailsElement);
$.getJSON(contributor.url).then(individual_contributor => {
userDetailsElement.append(
contributorDetailsHtml(individual_contributor)
);
});
}
});
.users {
min-width: 90px;
min-height: 90px;
margin-bottom: 0.5em;
}
.avatar {
float: right;
width: 10%;
}
.login {
margin-top: 0.5em;
font-size: 1.1em;
text-decoration: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
</head>
<body>Here, dynamic statistics are available regarding this repository in GitHub.
<div id="statistics">
<h3 id="heading"></h3>
<ul id="stats"></ul>
<h4>Contributors</h4>
<hr>
<ol id="contributors">
</ol>
</div>
</body>
</html>
Im building a random DogAPI image generator, where you put a number from 1-50 into a form text box, hit send, and it displays random dog photos of that amount.
Im almost there. If you put '1' into the text field, it will return 1 random image! But the issue is when you put 2 or more. It prints to the console just fine, showing you the number you chose in the form of links to those images, but on the main page, it shows a broken image link. They are all inside of an array, inside of an object... im just confused on how to show all images in object and not just 1 alone.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>How Many?</title>
<link rel="shortcut icon" href="#">
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="container">
<h1>How Many Dog Pics Do You Want?</h1>
<p>Pick a number between 1-50</p>
<form>
<input class="number" value="3" type="text" placeholder="1-50?" required>
<input type ="submit" value="Show me the doggies!">
</form>
<section class="results hidden">
<h2>Here you go!</h2>
<img class="results-img" alt="placeholder">
</section>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script src="index.js"></script>
</body>
</html>
CSS:
* {
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
}
.container {
max-width: 600px;
margin: 0 auto;
}
.hidden {
display: none;
}
JS:
'use strict';
function getDogImage(text) {
fetch(`https://dog.ceo/api/breeds/image/random/${text}`)
.then(response => response.json())
.then(responseJson => displayResults(responseJson));
}
function watchForm() {
$('form').submit(event => {
event.preventDefault();
var text = $('.number').val();
if(text < 50){
getDogImage(text);
}else{
alert('Number must be between 1-50')
};
});
}
function displayResults(responseJson) {
console.log(responseJson);
//replace the existing image with the new one
$('.results-img').replaceWith(
`<img src="${responseJson.message}" class="results-img">`
)
//display the results section
$('.results').removeClass('hidden');
}
$(function() {
console.log('App loaded! Waiting for submit!');
watchForm();
});
Here is a sample of what you're going to have to do. You can probably do this in an ES6 way but here is my working example below. This will print out the array in your object and allow you to iterate so you can print the image urls out. You can see the working example here on my Codepen -
https://codepen.io/CodeHero1/pen/JjoEYMv
var messageObject = { message: [
'https://images.dog.ceo/breeds/rottweiler/n02106550_12828.jpg',
'https://images.dog.ceo/breeds/sheepdog-english/n02105641_6875.jpg',
'https://images.dog.ceo/breeds/terrier-lakeland/n02095570_4656.jpg' ], status:
'success' };
for(var i=0; i < messageObject.message.length; i++){
console.log(messageObject.message[i]);
}
I took this a step further in my CodePen example and have a live working example of returning the images with Jquery append. I'll also post the most important piece of this code here. I have refactored your function a little to give you a better example. Please see below.
function displayResults(responseJson) {
console.log(responseJson);
for(var i=0; i < responseJson.message.length; i++){
console.log(responseJson.message[i]);
$('.results').append(
`<img src="${responseJson.message[i]}" class="results-img">`
);
}
//display the results section
$('.results').removeClass('hidden');
}
I am trying to use angular drag and drop http://codef0rmer.github.io/angular-dragdrop, but when I am trying a basic example, i am getting the error. My code -
<apex:page standardStylesheets="false" sidebar="false" showHeader="false">
<style>
table, th , td {
border: 1px solid grey;
border-collapse: collapse;
padding: 5px;
}
</style>
<html ng-app="myApp">
<link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap-responsive.min.css" rel="stylesheet" />
<div ng-controller="dragDropController">
<div class="row-fluid">
<div class="span6">
<div class="btn btn-primary" data-drag="true" ng-model="list" jqyoui-draggable="{animate: true}">{{list.title}}</div>
</div>
<div class="span6">
<div class="thumbnail" data-drop="true" ng-model="droppedList" jqyoui-droppable="{beforeDrop: 'beforeDrop'}"></div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<script src="{!$Resource.AngularDragDrop}" />
<script>
angular.module('myApp', ['ngDragDrop']).controller('dragDropController', function($scope, $http) {
$scope.list = {title : 'Drag me..!!'}
$scope.droppedList = {title: 'Drop place'};
$scope.beforeDrop = function() {
console.log('Before dropping..!!');
};
});
</script>
</html>
</apex:page>
Can someone help me with same.??
I have tried using same different versions of angular and also tried copying angular version from the actual site example but still facing same error
Thanks,
Ray
The beforeDrop function should return a promise (documentation).
The plugin executes your beforeDrop, where you would typically ask the user for confirmation, and then it "drops" (or not).
As you are not waiting for user input, to get rid of the error you could inject $q and return the dummiest promise, so to speak:
$scope.beforeDrop = function () {
console.log('Before dropping..!!');
return $q.when();
}
But the final look of beforeDrop will be more like:
$scope.beforeDrop = function () {
// open modal
// ...
return modalPromise;
}
I seem to make a mistake in the following:
html: index.html, main.html, etc
js: jQuery, jQuery UI, own.js, own_main.js
The end result should be an index page that based on a menu choice loads a html in a div.
The HTML that loads has a button element that I want to use with jQuery UI.
Index.html
<html lang="us">
<head>
<meta charset="utf-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Dev</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="css/kendo.dataviz.default.min.css" rel="stylesheet" />
<link href="css/kendo.dataviz.min.css" rel="stylesheet" />
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/bootstrap-theme.min.css">
<link rel="stylesheet" href="css/main.css">
<link href="css/jquery-ui-1.10.3.custom.css" rel="stylesheet">
<link href="css/typ.css" rel="stylesheet" />
<script src="js/modernizr-2.6.2-respond-1.1.0.min.js"></script>
<script src="Scripts/jquery-2.0.3.js"></script>
<script src="js/jquery-ui-1.10.3.custom.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/typ.js"></script>
<script src="js/typ-persons.js"></script>
</head>
<body>
<div id="content"></div>
</body>
</html>
typ.js file
function currentLoc(goToLoc) {
if (CheckLogin() == 0) {
//Not logged in, go to main
$("#content").load("/main.html");
window.localStorage.globalLocation = "/main.html";
} else {
if (goToLoc == '') {
console.log("No GoToLoc: " + goToLoc);
if (window.localStorage.globalLocation == '') {
console.log("No Global location");
$("#content").load("/main.html");
window.localStorage.globalLocation = "/main.html";
} else {
console.log("Global Location " + window.localStorage.globalLocation);
$("#content").load(window.localStorage.globalLocation);
}
} else {
console.log("GoToLoc " + goToLoc);
$("#content").load(goToLoc);
window.localStorage.globalLocation = goToLoc;
}
}
}
persons.html
<script src="js/typ-persons.js"></script>
<div class="container">
<style>
#toolbar {
padding: 4px;
display: inline-block;
}
/* support: IE7 */
* + html #toolbar {
display: inline;
}
</style>
<div id="toolbar" style="width:100%;" class="ui-widget-header ui-corner-all">
<button id="btnNew" ></button>
<button id="btnSave"></button>
<label for="persons">Find Person by Name or ID: </label>
<input type="text" class="input-sm" id="persons">
<input type="hidden" id="person-id">
</div>
</div>
typ-persons.js
$(function () {
$("#btnNew").button({
text: false,
label: "New Person",
icons: {
primary: "ui-icon-document"
}
})
.click(function () {
});
$("#btnSave").button({
text: false,
label: "Save",
disabled: true,
icons: {
primary: "ui-icon-disk"
}
})
.click(function () {
});
});
On the persons page there is also an autocomplete element with json data.
This works like a charm.
The problem is that the toolbar does not get the buttons applied from the typ-persons.js.
When I add the jQuery UI to the persons.html the buttons do work and get styled as they are supposed to.
The problem then is that jQuery UI loads twice and the autocomplete drowdown disappears on mouse over.
Kind of a paradox here and I would like both to work.
Thanks for your help,
Joris
I have the hunch that your persons.html file is the main.html addressed in the code. Otherwise I can't see where do you load persons.html or what are you loading when you load main.html.
Why are you adding typ-persons.js to persons.html, if you already have it in your main html file? In the way it's added, there's going to be double binding on button clicks. More than once, I believe. It would work on first load and then screw button behavior for good.
EDIT: After OP clarifications, these are my suggestions.
First: instead of putting new JS into persons html, make it just plain html. Make sure you don't use id attributes when that content is prone to be loaded several times. In that case, it's best to use classes.
<div class="container">
<style>
#toolbar {
padding: 4px;
display: inline-block;
}
/* support: IE7 */
* + html #toolbar {
display: inline;
}
</style>
<div id="toolbar" style="width:100%;" class="ui-widget-header ui-corner-all">
<button class="btnNew" ></button>
<button class="btnSave"></button>
<label for="persons">Find Person by Name or ID: </label>
<input type="text" class="input-sm" id="persons">
<input type="hidden" id="person-id">
</div>
</div>
Second: since you won't load new JS in that ajax call, you need to give the new buttons their behavior somewhere, right? Try to do that after they're appended, using jQuery's callback. I'd reccomend you use get method instead of load to have a bit more control on new content. Instead of
$("#content").load("/persons.html");
Try
$.get("/persons.html",function(responseText) {
var newElement=jQuery(responseText);
$("#content").append(newElement);
$(".btnNew", newElement).button({
text: false,
label: "New Person",
icons: {
primary: "ui-icon-document"
}
}).click(function () {
});
$(".btnSave",newElement).button({
text: false,
label: "Save",
disabled: true,
icons: {
primary: "ui-icon-disk"
}
}).click(function () {
});
});
Third: whatever listener you need to be set on dynamic elements, delegate them to the document to avoid needing to redeclare it (with the risk of double binding). I see no examples of this in your original post, but if you have any case of click, focus, or blur listeners (to name a few) I'll include a practical example.