I have been using jQuery pretty long time, but I never learned AJAX, so here I come..
we have this code :
$('body').load('hello.txt');
Simple enough, now let's say I have multiple text files (I don't know their names) I want to load,
Can I do that ?
Maybe I need to loop all the text files and load them somehow ?
Thanks in Advance
Assuming you have text files in the server in a specific location you can do this:
HTML markup:
<div id="fileList">
here list of files will be loaded so that user can select which one to load
<div>
<div id="file-content">
content of selected file will be loaded here
<div>
JQuery part :
$.ajax({
url : "FileServer/GetFileNames", // this is just a url that is responsible to return files list
success : function(data){
//here a JSON data including filenames expected
$.each(data,function(i,item){
var $fileHolder = $("<div></div>");
$fileHolder.attr("filename",item.filename).click(function(){
$("#file-content").load($(this).attr("filename"));
}).html(item.filename).appendTo("#fileList");
});
}
});
JSON Structure expected
[
{
filename : "text1.txt"
},
{
filename : "text2.txt"
},
{
filename : "text3.txt"
}
]
implementing file listing in the server side is up to you.
Javascript does not have access to the local file system for obvious
security reasons. This is not possible.
Unless you are trying to loop through files on your server, in which
case you wouldn't want to use jQuery anyway but something like ASP.NET
or PHP or whatever framework you are using.
Foreach file in directory jQuery
UPDATE
Try this out
var files;
$.ajax({
url: "http://homepage/folder",
success: function (txt) {
files = txt.split('<A href="');
}
});
var fList = new Array();
$(files).each(function () {
if (this.indexOf('.txt') > -1) {
fList.push(this);
}
});
for (i = 0; i < fList.length; i++) {
fList[i] = fList[i].split('">')[0];
fList[i] = fList[i].replace('"');
}
for (i = 0; i < fList.length; i++) {
$('#idLoadHere').load(fList[i]);
}
Run FTP list command (there are various ways to do so, Web-Sockets is one..)
A simpler, more common ans secure-solution is a server-side listing of the files, and "cooking" the HTML (meaning- embedding the file-listing within it),
*you can use raw HTML or put it in var statement to be used by JavaScript (for example).
see following answer:
https://stackoverflow.com/a/30949072/257319
Related
Scala/Play gurus out there.
I'm trying to upload a file using AJAX, in Play 2.1 (RC1). For the client part I'm using eldarion/bootstrap-ajax and everything seems to be fine, except that the uploaded file is empty.
The front-end snippet:
...
<form action="#routes.Campaigns.upload" method="post" class="form ajax replaceable" data-replace=".replaceable">
<input type="file" name="picture">
<p><input class="btn" type="submit"></p>
</form>
...
Note that I had to use the explicit <form> tag instead of the #form helper, due to the fact that the required css class (data-replace) contains a dash, and therefore can not be used as a Symbol. But anyway. The called action in the controller looks like this:
def upload = Action(parse.temporaryFile) {
request =>
Logger.info("Trying to upload a file")
val resultString = try {
val file = new File("/tmp/picture")
request.body.moveTo(file, true)
"file has been uploaded"
} catch {
case e: Exception => "an error has occurred while uploading the file"
}
val jsonResponse = Json.toJson(
Map("html" -> Json.toJson("<p>" + resultString + "</p>")
)
)
Ok(jsonResponse)
}
I'm aware that as my development goes forward the file name should be more intelligently set, but for the moment being, /tmp/picture is for me as good a name as any other one.
The JSON response gets generated (with the "file has been uploaded" message within), and is sent back to the browser as the payload of the 200 response. The JSON is received and correctly used to modify the page (in this case, merely removing the very uploading form).
But the file, although appearing in the right moment and in the right place, is always empty:
larsson:tmp bruno$ ls -l /tmp/picture
-rw-r--r-- 1 bruno staff 0 7 Jan 03:07 /tmp/picture
That's specially strange, in my opinion, because the uploading code which uses a traditional multipart/form-data form, with no AJAX whatsoever, and an Action with parse.multipartFormData as a parameter, instead of parse.temporaryFile, works finely.
Any help will be very appreciated. Thanks in advance.
I don't know bootstrap-ajax, anyway if it hasn't dedicated support for uploading files via AJAX (and I didn't find any info about that possibility in its readme file) it will NOT send files with AJAX.
Reason: In standard JavaScript uploading files with AJAX is not possible due the security limits and there are some techniques to workaround this, mainly using iFrames, however I can't see nothing similar in the code of bootstrap-ajax so probably you need to modify it or use other solution.
Solution: There are some AJAX file uploaders, which works good with HTML5 ie. jQuery File Upload, which offers ajax upload, multi-file uploads, drag file to the drop zone etc.
In general HTML5 supports file uploads better than earlier versions of HTML, so you can build uploader easily without need of using additional plugins, take a look to this topic. As you can see it delivers possibilities to validate some data BEFORE the upload and also offers progress bars.
I'm currently trying to implement something like this and I got a first version working. This is how I do it:
In my Controller I define a method for uploading files. In my case I use Action.async since I save stuff to my MongoDB with reactivemongo. I have removed that code so that it do not complicate this example.
What I do in this example is that I upload a csv file, save it to disk and then produce the first row back as a string to the user. In real life the method produces a list back so that user is able to choose which column represent what an so on.
I use mighty csv for csv parsing. GREAT LIB!
Application:
def upload = Action.async(parse.multipartFormData) {
implicit request =>
val result = uploadForm.bindFromRequest().fold(
errorForm => Future(BadRequest(views.html.index(errorForm))),
form => {
import java.io.File
request.body.file("csvFile").map {
csv =>
val path = current.configuration.getString("csv.job.new.file.path").getOrElse("")
val name = DateTime.now().getMillis + ".csv"
csv.ref.moveTo(new File(path + name))
val settings = CSVReaderSettings.Standard(linesToSkip = form.linesToSkip)
val rows: Iterator[Array[String]] = CSVReader(path + name)(settings)
val firstRow = rows.next()
val test = firstRow match {
case xs if xs.size == 0 || xs.size == 1 => xs.mkString
case xs if xs.size > 1 => xs.mkString(", ")
}
Future(Ok(test))
}.getOrElse(Future(BadRequest("ahadasda")))
}
)
result
}
routes:
POST /upload #controllers.Application.upload
I use # before the controllers because I use DI with guice for my service classes.
Since we will use javascript for uploading we need to define our jsRoutes:
jsRoutes:
def javascriptRoutes = Action {
implicit request =>
import routes.javascript._
Ok(
Routes.javascriptRouter("jsRoutes")(
Application.upload
)
).as("text/javascript")
}
Remember to import in your template where you want to use the routes:
<script type="text/javascript" src="#routes.Application.javascriptRoutes"></script>
<script src="#routes.Assets.at("javascripts/app.js")#Messages("js.version")" type="text/javascript" ></script>
In my view template I have a regular helper form. There is some css style stuff I do to
change the looks and feel of the upload button and file chooser. But the input fields
are there.
index.scala.html:
<div class="csvContainer">
#helper.form(action = routes.Application.upload, 'enctype -> "multipart/form-data", 'id -> "csvUpload") {
#Messages("upload.row.skip")
#inputText(uploadForm("linesToSkip"), 'class -> "hidden")
<div style="position:relative;">
<div id="csvFile" style="position:absolute;">
#Messages("upload.choose")
</div>
<input id="uploadFile" type="file" name="csvFile" style="opacity:0; z-index:1;" onchange="document.getElementById('csvFile').innerHTML = this.value;" />
</div>
<p>
<input type="submit" value="#Messages("upload.submit")">
</p>
}
</div>
In app.js is where the ajax magic happens, remember I have not implemented any validation or cool html5 stuff yet as the progressbar and other handlers, described in besiors link.
I use regular JQuery.
app.js:
$('#uploadFile').change(function(){
var name = $(this).val().split("\\");
console.log(name[2]);
$('#csvFile').text(name[2]);
});
$('#csvFile').click(function(){
$('#uploadFile').click();
});
$("#csvUpload").submit(function(e) {
e.preventDefault();
var formData = new FormData();
formData.append('csvFile', $( '#uploadFile' )[0].files[0]);
formData.append('linesToSkip', $( "#linesToSkip").val());
jsRoutes.controllers.Application.upload().ajax({
data: formData,
processData: false,
contentType: false,
cache: false,
type: 'POST',
success: function(data){
alert(data);
}
});
});
I have removed a lot of code to simplify this example and I hope that I have not forgotten anything. Hope this helps!
I have a JSP page which shows items included in an Array (Just a very simple list).
In the background the Array might change i.e. adds a new Item or remove one.
How can I auto refresh the page when the Array changes?
There are 2 ways that are most popular to perform such operation
pool a method that would send 1 or 0 to see if you refresh the page or not
keep asking for that data array and populate it through javascript
Option 1
create a .jsp page and call it, for example, updateList.jsp
add a single method that will check if there is more data to be filled and output 1 or 0 like: out.println(1)
in your page, and using jQuery to simplify things
$.get("updateList.jsp", function(data) {
if(data !== null && data.length > 0 && data === 1) {
// refresh this page
document.location = document.location.href;
}
});
Option 2
create a .jsp page and call it, for example, data.jsp
add a single method that will output a JSON string containing all data you need to populate the list
in your page, and using jQuery and JsRender to simplify things
$.get("updateList.jsp", function(data) {
if(data !== null && data.length > 0) {
$("#my-list").html(
$("#my-template").render(data);
);
}
});
and in your HTML you will have:
<ul id="my-list"></ul>
<script id="my-template" type="text/x-jsrender">
{{for items}}
<li>{{:name}}</li>
{{/for}}
</script>
assuming your JSON would be something like:
item: [
{ name: "Name A" },
{ name: "Name B" },
{ name: "Name C" },
]
Once the JSP has been executed, the HTML code that it has generated has been sent to the browser, and there is no connection between the browser and the JSP anymore. If you want to refresh some part of the page, you need to poll the server using AJAX, or use WebSockets to maintain a connection between the page and the server.
To refresh page silently use AJAX. Below are some examples
Example 1
Example 2
Google Search
For a project I need to get the source code of web page of different other domains.
I have tried following code:
$('#container').load('http://google.com');
$.ajax({
url: 'http://news.bbc.co.uk',
type: 'GET',
success: function(res) {
var headline = $(res.responseText).find('a.tsh').text();
alert(headline);
}
});
Still I am not getting any results but just a blank alert box.
By default all browsers restrict cross-domain requests, you can get around this by using YQL as a proxy. See a guide here: http://ajaxian.com/archives/using-yql-as-a-proxy-for-cross-domain-ajax
For security reasons scripts aren't able to access content from other domains. Mozilla has a long article about HTTP access control, but the bottom line is that without the website themselves adding support for cross-domain requests, you're screwed.
This code is Working Perfectly with the help of JQuery and YQL
$(document).ready(function(){
var container = $('#target');
$('.ajaxtrigger').click(function(){
doAjax($(this).attr('href'));
return false;
});
function doAjax(url){
if(url.match('^http')){
$.getJSON("http://query.yahooapis.com/v1/public/yql?"+
"q=select%20*%20from%20html%20where%20url%3D%22"+
encodeURIComponent("http://www.yahoo.com")+
"%22&format=xml'&callback=?",
function(data){
if(data.results[0]){
var data = filterData(data.results[0]);
container.html(data);
} else {
var errormsg = '<p>Error: could not load the page.</p>';
container.html(errormsg);
}
}
);
} else {
$('#target').load(url);
}
}
function filterData(data){
data = data.replace(/<?\/body[^>]*>/g,'');
data = data.replace(/[\r|\n]+/g,'');
data = data.replace(/<--[\S\s]*?-->/g,'');
data = data.replace(/<noscript[^>]*>[\S\s]*?<\/noscript>/g,'');
data = data.replace(/<script[^>]*>[\S\s]*?<\/script>/g,'');
data = data.replace(/<script.*\/>/,'');
return data;
}
});
The solution for your case is JSON with padding or JSONP.
You will need an HTML element that specified for its src attribute a URL that returns JSON like this:
<script type="text/javascript" src="http://differentDomain.com/RetrieveUser?UserId=1234">
You can search online for a more in-depth explanation, but JSONP is definitely your solution for this.
Do the following steps.
1: Add datatype:jsonp to the script.
2: Add a "callback" parameter to the url
3: Create a javascript function with name same as "callback" param value.
4: The output can be received inside javascript function.
Found one more solution for this :
function getData(url){
if(url.match('^http')){
$.get(url,
function(data){
process(data);
}//end function(data)
);//end get
}
}
This is really a pretty easier way to handle cross-domain requests. As some of the sites like www.imdb.com rejects YQL requests.
I use this jQuery Tags Input plugin:
jQuery Tags Input
but I can't get the values on my php file.
If you are trying to get the individual values using jQuery you can use:
(This is assuming the text input you made into a tag input has an id of "keywords")
$('#keywords').tagsInput({
'height':'auto',
'width':'350px',
'defaultText':'',
'delimiter': '|'
});
/*The delimiter option above overrides the default comma delimiter in the plugin allowing commas in tags if you prefer that...*/
var $keywords = $("#keywords").siblings(".tagsinput").children(".tag");
var tags = [];
for (var i = $keywords.length; i--;) {
tags.push($($keywords[i]).text().substring(0, $($keywords[i]).text().length - 1).trim());
}
/*Then if you only want the unique tags entered:*/
var uniqueTags = $.unique(tags);
alert(uniqueTags.toSource());
To get the list of emails from:
<input type="text" name="to_addresses" class="to_addresses" data-role="tagsinput" >
I use:
$emails = []
$.map($(".tagsinput span span"),function(e,i){
$emails.push($(e).text().trim());
})
Works for me, thought I'd share it.
$("#btn").click(function () {
var $tagWord = $("#tags_2").siblings(".tagsinput").children(".tag");
var tags = [];
for (var i = $tagWord.length; i--; ) {
tags.push($($tagWord[i]).text().substring(0, $($tagWord[i]).text().length - 1).trim());
}
/*Then if you only want the unique tags entered:*/
var uqTags = $.unique(tags);
alert(uqTags.toSource());
});
using jquery you can do it in one line:
$.map($('.tag span'),function(e,i){return $(e).text().trim();})
$("input").tagsinput('items')
["Amsterdam","Washington","Sydney","Beijing","Cairo"]
$("input").val()
"Amsterdam,Washington,Sydney,Beijing,Cairo"
can you provide an example of what is POSTed? you can do so by pointing your form to go to api.fatherstorm.com?query and copying the json data that it gives you
it change the hidden input value, and will post the data when you click submit , you can test it by a simple php script. print_r($_POST) to see it.
Based on sagivo answer you can write a function like this :
function getKeywords() {
return $.map($('.tag span'),function(e,i){
return $(e).text().trim();
});
}
That will return an array of keywords present in the input.
Like this [ "there", "it", "is" ]
So I have my first MVC2 site that I'm working on and naturally I'd like to throw some AJAX in there. The problem is, is that I don't know how to get the URL for the action when passing in a URL parameter. Let me explain. The examples I've seen so far show the developer passing in strings like '/MyController/MyAction'. That's great, except if your controllers are not in the root directory of your website (as is the case in my situation). I could always use relative URLs like 'MyAction' except if the URL contains parameters that doesn't work either. Consider http://example.com/myroot/MyController/MyAction vs http://example.com/myroot/MyController/MyAction/PageNumber/SomeOtherValue. Now the relative URL will be incorrect.
In the ASPX code, this is easy. I just write in <%= Url.Action("MyAction") %>. But how do I do this in my javascript file?
This is part of the long-standing issue that including server-sided code in JavaScript files is not really possible :(. (Without serious hacks, that is.)
The best solution is to include the action URL inside your HTML file somewhere, then get that value from JavaScript. My suggestion would be something like this:
<!-- in your view file -->
<form id="MyForm" action="<%: Url.Action("MyAction") %>"> ... </form>
<!-- or -->
<a id="MyLink" href="<%: Url.Action("MyAction") %>"> ... </a>
combined with
// In your .js file
$("#MyForm").submit(function ()
{
$.post($(this).attr("action"), data, function (result) { /* ... */ });
return false;
});
// or
$("#MyLink").click(function ()
{
$.getJSON($(this).attr("href"), data, function (result) { /* ... */ });
return false;
});
This feels semantically clear to me, and in some cases even creates degradable fallback behavior for when JavaScript is turned off.
You can't do this in your JavaScript file directly, however you can pass these dynamic values into your script by way of a script initializer. Consider the following example:
External Js file
ShoppingCart = function() {
this.settings = {
AddProductToCartUrl: '',
RemoveFromCartUrl: '',
EmptyCartUrl: '',
UpdateCartUrl: ''
};
};
ShoppingCart.prototype.init = function(settings) {
this.settings = jQuery.extend(this.settings, settings || {});
};
HTML/View
<script type="text/javascript">
var cart = new ShoppingCart();
cart.init({ AddProductToCartUrl: '<%=Url.Action("MyAction")%>' });
alert(cart.settings.AddProductToCartUrl);
</script>
Simple: tell your javascript what the correct URL is.
Tactically, you can get there alot of ways, but they basically break down into two techniques:
Have a server-side generated javascript "configuration" so you can do something like var url = siteConfiguration.SITEROOT + 'products/pink-bunny-slippers' Note this file can be a normal MVC view, the only trick is you have to tell the controller to send a text/javascript header rather than text/html.
Basically, dependency inject it into your script. IE function wireUpAjaxLinksToService(linkIdentifier, serviceEndpoint) where you call using something like wireUpAjaxLinks('a.ajax', '<%= Url.Action("MyService", "Services") %>')