Why does my jQuery work inline but not externally? - javascript

I've been trying to learn how to implement AJAX and so far I've been tinkering with this jQuery example.
The code is located at static/js/form.js
(function ($, window, document) {
/* globals window, jQuery, document, console */
// enable this return statement to disable Ajax submission
// return;
$(document).ready(function () {
var myForm = $('#myForm');
myForm.on('submit', function (e) {
e.preventDefault();
var data = myForm.serialize();
$.post('/my-ajax-endpoint', data, function (result) {
if (result.success) {
alert(result.message);
} else {
alert('Error: ' + result.message);
}
console.log(result);
});
})
});
}(jQuery, window, document))
My html works when I have the above inline like this:
<html lang="en">
<head>
<title>Flask-WTF + Ajax Example </title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
{% block content %}{% endblock %}
<script type="text/javascript">
(function ($, window, document) {
/* globals window, jQuery, document, console */
// enable this return statement to disable Ajax submission
// return;
$(document).ready(function () {
var myForm = $('#myForm');
myForm.on('submit', function (e) {
e.preventDefault();
var data = myForm.serialize();
$.post('/my-ajax-endpoint', data, function (result) {
if (result.success) {
alert(result.message);
} else {
alert('Error: ' + result.message);
}
console.log(result);
});
})
});
}(jQuery, window, document))
</script>
</body>
</html>
But when I try to reference it as an external file like this:
<head>
<title>Flask-WTF + Ajax Example </title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type=text/javascript src="{{url_for('static', filename='js/form.js') }}"></script>
</head>
It doesn't seem to do anything.
I've also tried to put it just before </body> tag and still no go.
I don't have any working knowledge of JavaScript or jQuery, so if it's something simple then I apologize in advance. I am learning Flask and I wanted to try submitting form data without refreshing and it led me to down this rabbit hole.
EDIT: form.js shows up in console under sources but it's completely blank?

I'm the author of the Flask Ajax Example project that you're working with. I've added a new branch that moves the JS into a separate file that's now inside of a static directory: https://github.com/YellowSharkMT/flask-ajax-example/tree/example-with-static-js-file
I can't say for certain what the issue may have been - the url_for function that you were using in your template above should have done the trick. In my update, I simply added this line to the home.html template:
<script src="{{ url_for('static', filename='js/form.js') }}"></script>
And that's obviously nearly the same thing that you had above. One thing I'll add about Flask is that my example did NOT have debug mode enabled, and I've now enabled that in a separate commit. It makes development a bit easier by adding features like auto-reloading (of the python server) and less-aggressive caching. Go ahead and check that branch out, and let me know if you have any issues - good luck!

Related

How to call node js function from node js client side

I am playing around with an html template and I have noticed that the developer doesn't use RequireJS or anything else to require and call different functions from other node files. Instead, they used this in the html file to initialise and call the function:
<script src="../../assets.js/test.js"></script>
<script type="text/javascript">
$(document).ready(function(){
test.initSomeFunction();
});
</script>
And I've got the below code in assets/js/test.js which defines initSomeFunction in javascript:
test = {
initSomeFunction: function() {
//Some code
}
initAnotherFunction: function() {
//More code
}
}
(It would be helpful if someone can tell me what this method is called so that I can research it more.)
My problem arises when I try to do the same thing in my node app in the home directory /main.js. The node app works fine on its own but when I add something like this:
test2 = {
initMyFunction: function() {
console.log("I finally decided to work! Good luck...");
}
}
and modify my html file like this:
<script src="../../main.js"></script>
<script type="text/javascript">
$(document).ready(function(){
test.initSomeFunction();
test2.initMyFunction();
});
</script>
then it won't work. Can someone please point me to the right direction as I don't even know what to Google. I am trying to avoid using RequireJS or anything else as I am a total beginner and the method that the developer used sounds so simple and tempting.
I wish this answer will help you:
I am using express, so I do this to solved your problem!
main.js file's position:
modify app.js add:
app.use(express.static(path.join(__dirname, '/')));
Then, in the view file:
<html>
<head>
<script src="public/javascripts/jquery-1.10.2.min.js"> </script>
<script src="main.js"></script>
</head>
<body>
<script>
$(function () {
//test.initSomeFunction();
test2.initMyFunction();
})
</script>
</body>
</html>
Open the chrome Developer Tools. You will see the result.

Head.js weird action

I'm trying to use head.js. Getting some weird action. Below works but if I comment out "alert('hi')" in the script in the BODY, then the head.js doesn't seem to work.
So I tried commenting out all the head.js stuff and used a standard tag for each JS library. And it works as expected. But when using Head.js, it fails if the "alert('hi')" is commented out. Obviously, for production, I want to remove this alert but then I get this error message: "ReferenceError: $ is not defined" ... ??? But if I uncomment out the alert, then it all works and pulls data from the DB ???
Any thoughts?
<head>
<title></title>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/headjs/0.99/head.min.js">
</script>
<script type="text/javascript">
head.js(
/* root level */
"http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js",
"http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js",
"/assets/scripts/external/_references.js",
"../../assets/scripts/external/jquery.unobtrusive-ajax.min.js",
"../../assets/scripts/external/jquery.validate-vsdoc.js",
"../../assets/scripts/external/jquery.validate.min.js",
"../../assets/scripts/external/jquery.validate.unobtrusive.min.js",
"../../assets/scripts/external/knockout-2.3.0.js",
"../../assets/scripts/external/modernizr-2.6.2.js",
"/assets/css/Index.css",
"assets/css/OrangeCounty.css"
);
</script>
</head>
<body>
<div id="list"></div>
<script>
alert('hi');
$.getJSON("http://localhost/webapi/api/ccc", function (result) {
$.each(result, function (i, field) {
$("div").append(field.Code + " " + field.Country1 + "<br/>");
});
});
</script>
</body>
The alert() stalls the script execution enough for jQuery to actually load. Head.js loads the scripts in parallel and doesn't block, so you have to use it with a callback:
head.js(..., function() {
// Your code
});
Or put that code into a separate script file and put it after jQuery in your head.js call.

How to make JQuery DatePicker work after dynamically loaded in a partial view?

I have lost jquery datepicker functionality in this scenario...
1- Originally I had a normal view, which worked fine, having this code for date input...
<input type="text" name="date_start" id="date_start"
value="#(Model.TimeStart)" />
<script language="javascript" type="text/javascript">
$("#date_start").datepicker();
</script>
2- Then, I converted that view in a partial view which is dynamically loaded with...
$('#TargetEmptyDiv').load("/MyController/MyAction");
3- The partial view loads ok, the data can be (manually) entered and all its fine. The only problem is that the jquery datepicker is no longer working. I tryed to assign it after the loading, using this...
$('#TargetEmptyDiv').load("/MyController/MyAction",
function () { $("#date_start").datepicker(); });
That did not work.
4- Later I've learned that jquery provides the live() and delegate() functions which are capable of attach javascript code to elements loaded "now and in the future". So, I tryed this in the document initialization...
<script type="text/javascript">
$(document).ready(function () {
$("#date_start").live("click", function () { $(this).datepicker(); });
});
</script>
and later also...
<script type="text/javascript">
$(document).ready(function () {
$("#date_start").delegate("click", function () { $(this).datepicker(); });
});
</script>
none of which worked, maybe because they directly reference to the "click" event, but the datepicker is "attached" (if that is the proper term) to the whole element.
So, question is:
How to make the jquery datepicker work on elements loaded after dynamic load???
Thanks for your time!
SOLVED:
The problem was that at the bottom of _Layout.cshtml there is this line...
#Scripts.Render("~/bundles/jquery")
..which loads the minified version of jquery libraries (already referenced by myself).
So, the libraries were loaded twice and got invalid, producing the error "datepicker() is not a function".
Just commenting or deleting that line, makes all work fine!
Put the following jQuery in the base view, not the partial view
<script>
$(document).ready(function () {
$(document).on('focus', '.datefield', function () {
$(this).datepicker();
});
});
</script>
This will work when a partial view is dynamically loaded and on page load.
Your approach in #3 looks to me like it should have worked, so it seems like you need to do some debugging. Try this:
Get the Firebug extension, if you use Firefox (Chrome has dev tools built in)
Add a debugger line to your code (see below for example)
Load your page up with Chrome or Firebug/Firefox (or any other browser's dev tools)
What should happen is that your browser will pause at that point. However, if things aren't working as you expect, it might not be hitting that code at all, and then you'd get no pause.
If you do get a pause, use the console to inspect the value of $("#date_start"); it's possible that jQuery selector isn't grabbing what you think it is.
Here's a debugger example with your code:
$('#TargetEmptyDiv').load("/MyController/MyAction", function () {
debugger;
$("#date_start").datepicker();
});
On your partial page say "/MyController/MyAction",
Partial Page Code:
<div>
<form>
<!--Other Elements-->
<input type="text" id="adate" name="adate" title="date" />
</form>
<script type="text/javascript">
$(document).ready(function(){
$( "#adate" ).datepicker();
});
</script>
</div>
Full Page(Page From Where You are Calling Ajax Request) Code:
<div id="TargetEmptyDiv"></div>
<script type="text/javascript">
function abc(){
$.ajax({
type: "POST",
url: "/MyController/MyAction",
success: function(response)
{
$("#TargetEmptyDiv").html(response);
}
});
}
</script>
call function abc and you are done.assuming you already have all jquery files loaded.
In my case, the Id of the date field that I tried to hook up the datepicker to was not what I thought it was. I am using ViewModels and the id got prefixed with the ViewModel name of my partial view.
machineghost's answer put me on to it.
So I now use Charly's answer but instead of #BirthDate I have #IdentityModel_BirthDate:
<script>
$(document).ready(function () {
$(document).on('focus', '#IdentityModel_BirthDate', function () {
$(this).datepicker({
format: 'MM/dd/yyyy',
changeMonth: true,
changeYear: true,
yearRange: "-90:+0"
});
});
});
</script>
All you need to make the datepicker work is steps 1-3.
Here's a sample:
http://jsfiddle.net/delrosario/Xd8py/
You got datepicker to work without loading the markup dynamically and your pseudo code for the dynamic version is sound from steps 1-3. The thing you need to check now is to make sure that your dependencies are being loaded before your main program (in this case make sure that jquery and jquery ui are available before running the request + datepicker setup).
1) load jquery
2) load jquery ui
3) wait till the dom is ready or the element that will contain your payload is ready
4) execute your main app that does steps 1-3 from your description.
So it would be something like this.
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="path-jquery-ui-css" />
<script src="path-to-jquery"></script>
<script src="path-to-jquery-ui"></script>
<script id="main_app">
(function () {
// wait till dom is ready before executing our code,
// in this case steps 1-3.
});
</script>
</head>
<body>
<div id="datepicker_target">datepicker target</div>
</body>
</html>
After invoking ajax, hookup your jquery to the 'ajaxStop' event. (SEE: '#section Scripts' )
$(document).ajaxStop handles the post ajax jquery call and now datapicker works after ajax call(s). yea...
Note: $(document).ready... handles the initial page load datapicker decoration, but after an ajax form reload, datepicker jquery was not executed...
#model Q_Admin.Models.AllQAViewModel
<div id="mainContent">
#using (Ajax.BeginForm("EAAll","Answer",new AjaxOptions {
UpdateTargetId = "mainContent",
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace
}))
for (int i = 0; i < Model.VMs.Count; i++)
{
#switch (Model.QAVMs[i].qN.Node1.TypeAnswer.AnswerType.Trim().ToUpper())
{
case "DATETIME":
#Html.TextBoxFor(m => m.VMs[i].CurrentNodeText,
new { #class = "datepicker", #id = "datepicker" });
break;
case "DROPDOWNLIST":
#Html.DropDownListFor(m => m.QAVMs[i].AnswerRecord.AnswerID,
new SelectList(Model.QAVMs[i].answerNodes, "ID", "NodeText.Text", Model.QAVMs[i].SelectedNodeID),
"-- Select an Answer --",
new { #onchange = "$(this).parents('form:first').find(':submit')[0].click();" }) }
break;
default:
break;
}
}
</div>
#section Scripts{
<script type="text/javascript">
$(document).ready(function () {
// debugger;
$("#datepicker").datepicker(
{
dateFormat: "mm/dd/yy",
constrainInput: true
});
});
$(document).ajaxStop(function () {
// debugger;
$("#datepicker").datepicker(
{
dateFormat: "mm/dd/yy",
constrainInput: true
});
});
</script>}
I've had this problem before. In my situation I had <script src='jQueryUI.js'></script> referenced at the bottom of the page. Moving the reference to the top of page fixed it for me.
Seems like #3 should works. But maybe you can try a hacky way like this:
<script type="text/javascript">
$(document).ready(function () {
$(this).on("mousedown", "#date_start", function (e) {
$(this).datepicker(); e.preventDefault();$(this).click();
});
});
</script>
I have this working
Action Method:
public ActionResult GetControl()
{
return View("_partial");
}
Main View:
<div id="TargetEmptyDiv"></div>
<script type="text/javascript">
$(function () {
$('#TargetEmptyDiv').load("/Home/GetControl");
});
</script>
Partial View:
#{
Layout = "";
}
<input type="text" name="date_start" id="date_start" />
<script type="text/javascript">
$(function () {
$("#date_start").datepicker();
});
</script>
Of course you have to remember to include jquery-ui.js in your Layout
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.20.min.js")" type="text/javascript"></script>
My suspicion is that your JS is executing, but you have improperly referenced jquery-ui. I recommend adding all jquery libraries at a higher level than a partial view. Try putting the <script src="jquery-ui.js"> tag in either the page or the layout, not the partial view. If this doesn't fix it, try putting alert("test"); in your javascript code to make sure that it is executing.
I had the exact same problem. If using ajax, then bind the below jquery function to the document. Each time ajax is executed, this will fire. Check out the api doc here - http://api.jquery.com/category/ajax/global-ajax-event-handlers/
$(document).ajaxComplete(function (){//your code here})
I had the same problem, solved using a previous version of JQuery-UI. In my case goes to use the version 1.9.2 and 1.10.3 to JQuery version 1.10.1. Know the reason, but I think the latest versions bring some problems compactness, so I chose to use always backward to the past.
I hope it will be useful
<script type="text/javascript">$(function () {$("#datefield").datepicker();});</script>
just load this line with the content you have to load by ajax
hi: you put below code in load document event script tag in your partial view :
$(function(){
$("#date_start").datepicker();
})

head js + jquery.validate.unobtrusive + custom validators

I'm using head.js (http://headjs.com) to do async loading of my javascripts.
I have problem with jquery.validate.unobtrusive and custom validators
All custom validations should be loaded after jquery.validate and jquery.validate.unobtrusive, and I do it like following:
<head>
<script src="#Url.Script("jquery")"></script>
<script src="#Url.Script("head.load")"></script>
</head>
<body>
<!-- entire markup -->
<script>
head.js("#Url.Script("jquery.validate")", function () {
head.js("#Url.Script("jquery.validate.unobtrusive")", function () {
head.js("#Url.Script("custom-validations")");
});
});
</script>
</body>
The problem is that custom-validations script should be loaded after jquery.validate.unobtrusive but before document.onready event, because jquery.validate.unobtrusive uses document.onready to do it's black magic. But, when I'm using head.js document.onready event fired before scripts starts to load, and my custom validation does not work.
Is there any common solutions/workarounds to solve this kind of problems with async script loading?
Another problem that my customer does not want to see jquery.validate/jquery.validate.onubtrusive in <head> tag.
#Url.Script - helper method for locating js files.
I've found solution by myself. Need to use jQuery.holdReady() to hold 'document.ready' while all scripts depend on jquery.validate.unobtrusive will not load.
<head>
<script src="#Url.Script("jquery")"></script>
<script src="#Url.Script("head.load")"></script>
</head>
<body>
<!-- entire markup -->
<script>
head.js("#Url.Script("jquery.validate")", function () {
$.holdReady(true); // set semaphore for dom ready.
head.js("#Url.Script("jquery.validate.unobtrusive")", function () {
head.js("#Url.Script("custom-validations")", function () { //fires when all provided scripts are loaded
$.holdReady(false); // release semaphore and fire event
});
});
});
</script>
</body>
Try $.validator.unobtrusive.parse('#the_form_in_question') after the load.
This should work:
head.ready("#Url.Script("jquery.validate")", function () {
head.ready("#Url.Script("jquery.validate.unobtrusive")", function () {
head.ready("#Url.Script("custom-validations")",function(){
// your code here
});
});
});
If you use jquery, you could add the scripts via getScript method which fires a callback when the script is loaded, so that can help :
$(document).ready(function(){
$.getScript("#Url.Script("jquery.validate")",function(){
$.getScript("#Url.Script("jquery.validate.unobtrusive")",function(){
$.getScript("#Url.Script("custom-validations")",function(){
// do your stuff here
});
});
});
});

JSONRequest.get unresponsive

I am trying to send get requests to the Google Places API with this code:
<script type="text/javascript" src="json2.js">
var googleQuery;
function load() {
googleQuery = JSONRequest.get(
"https://maps.googleapis.com/maps/api/place/details/json?reference=3af0d044d45cd8587d9a3522bc98a95d4f60c6a8&sensor=true&key=xxxxxxxxxxxxxxxx",
function (googleQuery, value, exception) {
if (value) {
processResponse(value);
}
else {
processError(exception);
}
}
);
}
</script>
And calling the load function in the body onload.
<body onload="load()">
</body>
I am including the src="json2.js" in this <script> instead of in its own <script>, since I was getting a "JSONRequest is undefined" error...but I am still getting a strange "load is undefined" error.
Am I going about this JSON request correctly?
Try:
<script type="text/javascript" src="json2.js"></script>
<script type="text/javascript">
var googleQuery;
function load(){
googleQuery = JSONRequest.get(
"https://maps.googleapis.com/maps/api/place/details/json?reference=3af0d044d45cd8587d9a3522bc98a95d4f60c6a8&sensor=true&key=xxxxxxxxxxxxxxxx",
function (googleQuery, value, exception) {
if (value) {
processResponse(value);
} else {
processError(exception);
}
}
);
}
</script>
You can't have JavaScript code inside a script tag which has the src attribute. You should place the inline code on another script tag, otherwise it won't be executed.
Replace the line :
<script type="text/javascript" src="json2.js">
with
<script type="text/javascript" src="json2.js"></script>
<script>
Your JS code is being ignored since you specified an src attribute.
JSONRequest is more so just a proposal which browsers can implement at their will (I think Firefox does).
I'm not sure if there are any libraries that can be script sourced to in order to use JSONRequest, but an alternative is to use flyJSONP (http://alotaiba.github.com/FlyJSONP/#!/demo).
flyJSONP uses YQL (Yahoo Query Language) to do any cross domain post/get, and I highly recommend it (especially for google api's such as oAuth 2.0 and ClientLogin)... and it has a debugger mechanism.
Also, there is jankyPost (http://saunter.org/janky.post/). I have not used it but I'm sure I will and I like its concept. Its kinda clugy, or well... janky... but read about how it works (short paragraph) and you'll love it and want to build you own perhaps.
--Cody

Categories

Resources