Iterare through background images - javascript

I'm trying to make a dynamically background that changes images every x seconds. But i want the images to be sourced from a directory in a django project. I have this piece of code but is hardcoded and limited.
var header = $('body');
var backgrounds = new Array(
'url(static/media/backgrounds/1.jpg)'
, 'url(static/media/backgrounds/2.jpg)'
, 'url(static/media/backgrounds/3.jpg)'
, 'url(static/media/backgrounds/4.jpg)'
, 'url(static/media/backgrounds/5.jpg)'
, 'url(static/media/backgrounds/6.jpg)'
, 'url(static/media/backgrounds/7.jpg)'
, 'url(static/media/backgrounds/8.jpg)'
, 'url(static/media/backgrounds/9.jpg)'
, 'url(static/media/backgrounds/10.jpg)'
);
var current = 0;
function nextBackground() {
current++;
current = current % backgrounds.length;
header.css('background-image', backgrounds[current]);
}
setInterval(nextBackground, 5000);
header.css('background-image', backgrounds[0]);

Firstly you'll need to enumerate the images you want. For simple deployments, where static files will be on your filesystem (in STATIC_ROOT) and served from under /static/, something like
# Get absolute disk paths of files
backgrounds = glob.glob(os.path.join(settings.STATIC_ROOT, 'media', 'backgrounds', '*.jpg'))
# Turn into URLs
background_urls = [f'/static/media/backgrounds/{os.path.basename(bg)}' for bg in backgrounds]
will do; for a more robust solution, you'd probably want to use the staticfiles finders API to enumerate all files and turn them into URLs.
For serving that data to your view, a couple of options I can think of.
List the backgrounds in your view and pass the array into the template
Enumerate all of the background images' URLs into a list, pass it to the template
Render it into a JSON list: {{ background_urls|json_script:"backgrounds" }}
View returning Javascript fragment
Wire up a view that returns a JavaScript fragment with all the background URLs, e.g. var backgrounds = ["/static/foo.jpg"];
Use that in your view: <script src="{% url "background_list_js" %}"></script>
Your script would otherwise work as-is
View returning JSON payload
Wire up a view that returns a JSON object with all the background URLs, e.g. ["/static/foo.jpg"]
Use e.g. fetch() or another AJAX method to load the data before starting to change backgrounds
View returning a random background URL
Wire up a view that returns a JSON object with a single random background URL from the selection, e.g. {"url": "/static/foo.jpg"}
Use e.g. fetch() or another AJAX method to load the data every time you need a new background.
Custom template tag returning a Javascript fragment
Like option 1, but instead of having a separate view, register a simple template tag you can then use to inline the background array: <script>{% dump_backgrounds %}</script>

Related

update property in object loaded from js file - javascript

im very new in javascript and im trying to implement new function into existing project.
The background -
In html file i can see:
<script src="js/users.js" type="text/javascript"></script>
<script src="js/seating-plan.js"></script>
File seating-plan.js access object stored in users.js that contains:
var users = [
{"id": 1, "name":"first", "surname":"surname"},
{"id": 2, "name":"second", "surname":"surname"}
]
My question is: Can I change a property loaded from such object so the file will be changed? If so how to do it? I read some posts how to change object property but such approach will only changed already loaded object, not rewrite js file so i would be stuck with same result after refresh. Im guessing I will need to change how I initially load array object but if you know how to do it with my original aproach or how to do the second option in easy way please assist.
EDIT: localhost internal purpose (shared folder)
The approach I mentioned:
// Start of jQuery ready function
$(function () {
//can already access object
for (var i = 0; i < users.length; i++) {
//example of how i tried to rewrite property
if (users[i].id === 1){
users[i].name = "NewName";
}
}
.
.
.
If you want to change data on the server, then you must send an instruction to the server to change the data.
It would be a serious security risk if, by default, any web browser could change data on any HTTP server. The Google homepage would be vandalised on a second-by-second basis if that were possible!
Typically this will be a POST request (which you could make with a <form> or with XMLHttpRequest/fetch).
You then need server-side code (written in the language of your choice) which will update the data.
Typically you will want to store the data in a database and generate users.js (although changing it to JSON would probably be a better idea) on demand.

Static page with custom content depending on url

I used to use parts of the url address to add words to a page template when I worked with PHP.
I've started looking at static pages using https://gohugo.io and trying to get this function in JavaScript in order not to need to generate multiple pages (Although this is the point of static pages) since all url will use the same page template but with difrent text from the url.
Example (from my PHP site)
url = www.domain.tld/city/washington/
Where i get the word after /city/ and put the word "washington" in my page content.
url = www.domain.tld/city/somecityname/
Where i get the word after /somecityname/ and put the word "washington" in my page content.
I looked at https://gohugo.io/extras/datafiles/ and https://gohugo.io/extras/datadrivencontent/ but this wont fix it the way i want it to be. (although I have a csv file with the city names)
Page will be hosted on GitHub Pages so i can only use Javascript / jQuery for this function.
try this code for get city name
var qrStr1 = window.location.href;
var new1 = qrStr1.replace(':','');
var data1 = new1.split("/");
alert(data1[4]);// try with different index so you can find your value

Sending variable to javascript

I have a Rails application and I want to use Google Charts on a page. So in the view I load the javascript file (which contains the Google Charts code) to show the graph:
content_for(:head) do
= javascript_include_tag 'infograph'
#chart_div{"data-hours" => #billable_hours }
This all works nicely, the graph is shown. However, I have a variable ``#hours```I want to pass to the javascript file, because it contains the graph data. How can I do that?
I read about using a data label like #chart_div{"data-hours" => #billable_hours }, but I don't know how to use that in the Javascript file. Using alert(data('hours')); doesnn't seem to work. How can I do this? Thanks!
Initial data
Using data attributes is the correct way to initialize data in javascript : data is attached to DOM elements when you render the page, so javascript can access it when it is executed, on DOMReady.
Vanilla javascript
With plain javascript, you would have to retrieve it on dom element :
document.querySelect('#chart_div').getAttribute('data-hours')
Beware that it will always be a string (or undefined if attribute does not exist), so you have to do your typecasts yourself if you want to have anything else :
var myInt = parseInt(document.querySelect('#chart_div').getAttribute('data-hours'), 10)
jQuery
If you use jQuery, you can retrieve your data using .data() :
$('#chart_div').data('hours')
This will do type conversion for you and provide a quite simpler interface to access data attributes.
Be aware, though, that this is for initial data. If you change the value of data-hours after data container has already been initialized, it won't be reflected. So with the following html :
<div id="chart" data-hours="10"></div>
This will happen after DOMReady :
# data() is correctly initialized
$('#chart').data('hours') # => 10
# changing attribute does not reflect in data container
$('#chart').attr('data-hours', 7)
$('#chart').attr('data-hours') # => 7
$('#chart').data('hours') # => 10
# changing data container does not reflect in attribute
$('#chart').data('hours', 5)
$('#chart').data('hours') # => 5
$('#chart').attr('data-hours') # => 7
The thing to remember here is that jQuery's .data() method actually handles a separated container, which defaults are initialized from data-* attributes from dom element.
If you want to retrieve data from an element which initial data-* attribute has been changed, you have to use .attr() (and do typecast yourself).
Big or asynchronous data
If you begin to have a lot of data to pass, you should avoid using data attributes : I does not make sense to have a html page which data attributes count for the half or third of the page.
In that case, you should defer your js initialization and request for data through ajax. This is also how you pass data after page has already been initialized.
For example, if you're on a index page that loads a few Items on page initial load, then loads a huge collection of them through async javascript, you could do something like that, in your controller :
class ItemsController < ApplicationController
def index
respond_to do |format|
format.html { #items = Item.all.limit(5) }
format.json { render json: { items: Item.all.limit(1000) } }
end
end
end
With jQuery, you can use $.getJSON to retrieve your large collection :
$.getJSON( '/items', function(items){ console.log(items) });
You now can use your data in place of that console.log, with all common types (integer, float, array, object/hash, string) already casted as expected.
PS
Oh, by the way :
#chart_div{"data-hours" => #billable_hours }
There is a dedicated syntax for that :
#chart_div{ data: { hours: #billable_hours } }
It's especially useful as a shorthand when you have three of four data attributes.

base link and search api

I am attempting to query a database through an API which I don't fully understand. I have been sent an example of the API being used with a keyword search form. The form is an html file and uses jquery return JSON documents, format items into an array array, and display.
I tried to build the design of my application and manipulate the form to work within my pages. The file the uses the API requires that the a base link be used.
<base href="{{app_root}}">
If I remove this base link my functionality of the search is lost. If I use the base link all of presentation and CSS is lost.
I thought maybe I could change the base link dynamically when I needed to call the search file with:
<script type="text/javascript">
function setbasehref(basehref) {
var thebase = document.getElementsByTagName("base");
thebase[0].href = basehref;
}
//setbasehref("{{app_root}}");
setbasehref("{{app_root}}");
</script>
Then use setbasehref() to change it back to my original base link, but that didn't work.
I'm new to javascript and JSON, and I'm not entirely sure what app_root is doing. Any thoughts?

How should I handle Asp.net MVC URLs in javascript calls?

I am attempting to write a javascript heavy portion of my Asp.net MVC Web App (this portion of the website is a RIA using Extjs). However, I have come up to a standstill at the correct way to handle URLs in the javascript.
For example, right now I have an Ajax call to the List action in the ObjectsController, which resides in the Reading area. The List action takes a parameter of documentId (int). As of right now, this maps to /Reading/Objects/List since I have no changed routing yet (the site is too young at the moment to finalize routes). Normally in a view, to put this URL in a string I would do #Html.Action("List", "Objects", new { area = "Reading", documentId = 3).
However, this doesn't work when dealing with javascript, since javascript isn't parsed by a viewengine.
To get around this, I have a very small view that returns javascript constants, such as URLs, that is loaded prior to my main application's js files. The issue is that I can't call Html.Action for this action because at constant creation time I (obviously) do not know what documentId the ajax calls are going to be, and if you exclude documentId from the Html.Action call an exception occurs. The documentId could change during the normal workflow of the application.
How do I handle this? I don't want to hardcode the URL to /Reading/Objects/List because if I change my routing for this (for a more user friendly json API), or this web app isn't hosted on the root of the domain, the URL will no longer be valid.
How does everyone else handle MVC URLs in their javascript calls?
Here's a safe technique that I've been using. Even if your route changes, your JavaScript will automatically conform to the new route:
<script>
var url = '#Url.Action("List", "Objects", new { area = "Reading", documentId = "_documentId_")';
var id = 100;
var finalUrl = url.replace('_documentId_', id);
</script>
"_documentId_" is essentially a dummy placeholder. Then inside my JavaScript, I replace "_documentId_" with the proper id value once I know what it is. This way, regardless of how your route is configured, your URL will conform.
Update: Dec 20
I just saw this interesting blog post. The author built a library that allows you to build routes inside of your JavaScript file with intellisense support in VisualStudio.
http://weblogs.asp.net/zowens/archive/2010/12/20/asp-net-mvc-javascript-routing.aspx
Personally I use unobtrusive javascript and avoid mixing markup with javascript. AJAX calls are normally triggered by clicking on some buttons or links:
#Html.ActionLink("click me", "List", "Objects",
new { area = "Reading", documentId = 3 }, new { id = "foo" })
and then in a separate js file I would attach and handle the onclick event (example with jquery):
$(function() {
$('#foo').click(function() {
$('#resultDiv').load(this.href);
return false;
});
});
As you can I didn't need to use any hardcoded URL in my javascript file. URLs should always be handled by the routing engine and generated with html helpers.
If it was a <form> instead of a link I would simply handle the onsubmit event (the same way) and use the form's action attribute to get the URL.
UPDATE:
After pointing out in the comments section that the documentId is known only at client-side you could do this:
#Html.ActionLink("click me", "List", "Objects",
new { area = "Reading" }, new { id = "foo" })
And then:
$(function() {
$('#foo').click(function() {
$('#resultDiv').load(this.href, { documentId: '123' });
return false;
});
});
Turns out, this was all solved by using Url.Action() instead of Html.Action(). Url.Action() is (so far) allowing me to generate URLS without all of the parameters. I am assuming that this only works when the route does not specify the parameters in the target URL itself.

Categories

Resources