I have a rails app in which I would like only one view to be refreshed every five seconds. I put the following in assets/javascripts/application.js
function timedRefresh(timeoutPeriod) {
setTimeout("location.reload(true);",timeoutPeriod);
}
$(document).ready(function(){
timedRefresh(5000);
});
However this will cause every view to be refreshed every five seconds. How could I make this JavaScript apply to only one view?
(using Rails 3.2.5)
If you want to keep your JS in application.js you can simply check for the presence of a specific element and act accordingly. For example:
some_vew.html.erb
<div id = "refreshable">
<!-- So on and so forth... -->
</div>
application.js
$(function() {
// function timeRefresh()...
if ($('#refreshable').length) {
timedRefresh(5000);
}
});
You can make use of the tag in the bottom of your view.
some_view.html.erb
...
contents
...
<script type="text/javascript">
Put javascript code here...
</script>
This will make this script only available to someview.html.erb. The application.js makes the script global.
Related
I have a web application which uses MVC layouts, all of my views inherits from this page, in layout page I am using a jquery plug in (iCheck), now I have a page which also inherits from my layout but I don't want this page to use that plugin, in layout I have this script:
<script>
$(function() {
$('input').iCheck();
});
</script>
Now Is there any way to tell jQuery not use this plugin in that page?
The better approach instead of relying in viewbags and other server side codes is to use class in the elements as it's more clear what's the intention of the code.
Here's an example.
<input class="not-icheck" value="I'm a rebel!" />
...
<script>
$(function()
{
$('input:not(.not-icheck)').iCheck();
});
</script>
One way is this:
In layout replace the script code with this:
#{
bool? dontICheck = ViewBag.dontICheck;
}
if(!dontICheck.getValueOrDefault()){
<script>
$(function() {
$('input').iCheck();
});
</script>
}
This means iCheck will work at default. If you dont want it to work add this line into the view's action method which you dont want to use iCheck:
ViewBag.dontICheck = true;
A simple method is to add a class where you do not want this applied, eg:
<input class='noicheck' ...
then apply this in your selector:
$("input:not(.noicheck)").iCheck();
This will then work across your entire site without needing page-by-page changes or any changes to your viewmodel / viewbag etc and will still allow some controls to have this check applied.
I assume that your page has some specific class for styling (for example "special-page").
You can use that to identify that you are on that page and not to init jQuery plugin.
replace
$('input').iCheck();
with
if(!$(".special-page").length){
$('input').iCheck();
}
Replace the current script block you have with:
#if (IsSectionDefined("iCheck")) {
RenderSection("iCheck");
}
else {
<script>
$(function() {
$('input').iCheck();
});
</script>
}
Then in the view that you don't want this run, add:
#section iCheck {}
By defining the section, the layout will include the contents of the section, rather than the default code (your iCheck script), which will just be empty because nothing was provided within the curly brackets.
I am using Laravel 5 where I can make a master page (header, footer) and import every page's content in that master page.
I have a dropdown in my header (master page) and in javascript, I have a variable connected to it - var clickable = true;.
//Master Blade
#yield('content')
<script>
var clickable = true;
$('.dropdown).click(function() {
clickable = false;
})';
</script>
In my view (content), I have a function that I also want to change clickable = true;
//View
('.contentElement').click(function() {
clickable = true;
});
However, it doesn't recognise it. Is there a way that I can achieve what I want to?
Most likely you are referencing a variable that is in a different scope. It is hard to tell if that's the case with your minimal code provided but most likely this is why your variable is not being recognized.
You should not be writing JavaScript in different parts of your template, it will make for hard to maintain code. Instead, put all your JavaScript code in its own .js file and include it in your page.
There are many benefits of doing this, but mostly it will help you better structure your code and save pointless debugging time.
I found my answer. I created
<body>
<script>
var clickable = false;
</script>
....
#yield('content')
<script> /* rest of JS */ </script>
</body>
Using a method recommended by a user in a previous question I used just one document (index.php) to show different contents instead of creating one file for each one.
This is the code:
HTML
Home
More info
Contact Us
<div id="index">...index content...</div>
<div id="more_info">...more info content...</div>
JS
$(document).ready(function(){
function more_info(){
$('#index').hide();
$('#more_info').show();
}
});
PHP
<?php
if (isset($_GET['id_page'])) {
$id = $_GET['id_page'];
if ($id == 1) {
?>
<script>
more_info();
</script>
<?php
}
}
?>
That's not working. But if I change <script> more_info(); </script> for:
<script>
$(document).ready(function(){
$('#index').hide();
$('#quienes-somos').show();
});
</script>
It works. Why is this?
It looks like the problem you are having is because you are defining your more_info function inside of a function. This takes it out of the global scope which will not make that function accessible anywhere except for inside of your document ready function.
//more_info is now available globally
function more_info(){
$('#index').hide();
$('#more_info').show();
}
$(document).ready(function(){
//document ready code here
});
This should make the more_info execute when you output the JS function from PHP. Also it is good to note that since you are not executing the function on ready you will need to make sure the html is available for the JS to modify it. It is normally best practice to put all your JS just before the closing tag. This will ensure your html loads as quickly as possible and your JS will always have access to the HTML you are attempting to edit. With the JS in the head tag you need to make sure your JS is being called at the correct time using:
$(function() {
});
OR
$(document).ready(function() {
});
OR
$(window).load(function() {
});
All of these methods execute at different times during page initialization. With JS in the head tag your browser will need to download all the JS to the client before it can begin to render the HTML which will also add to time between going to the site and actually seeing the site.
What am doing is writing wizards using existing forms and list views. we want to combine these forms in single page. here is a script we have used to get form from url then called function to bind widgets. first line is loading content of form but bindWidgets is not working. While bindWidgets is working on preloaded content which is default loaded with page.
<script>
$(document).ready(function() {
$("#template_form").load("/push_templates/pushtemplate/create/ #zform");
bindWidgets();
});
</script>
Do we need to wait for load, as it seems that 2nd line is executed prior to content loaded. How can we go to wait stat or better way to call bind function after load complete.
Use this;
<script>
$(document).ready(function() {
$("#template_form").load("/push_templates/pushtemplate/create/ #zform", function() {
bindWidgets();
});
});
</script>
You can see demo here: jsfiddle
I make use of jQuery and history.js to manage dynamic transitions between partial-pages; such that I avoid reloading entire documents. Some of these partial-pages call their own unique javascript files. While the transitions between pages work well, remnants of executed javascript remain active after the partial page that called it has been dynamically replaced.
How can I unload javascript that was introduced with a dynamic page load, and later asynchronously replaced by another page?
The finer details
Master template
My master template (used for all pages) can be thought of as a simple:
<html>
<head>
<script>
//scripts to manage asynchronous loading of partial-pages into #content div
</script>
</head>
<body>
<div id="content"></div>
</body>
</html>
User profile
One partial page that renders inside the #content div is for a user's Profile:
<script src="profile.js"></script>
<form>
<input type="file" name="profile-picture">
</form>
The contents of profile.js are similar to:
$(function() {
$('input').change(function() {
// upload profile picture asynchronously
});
});
User settings
Another partial page that is loaded inside the #content div of the master template is the user's Settings:
<script src="settings.js"></script>
<form>
<input type="text" name="first-name">
<input type="text" name="last-name">
</form>
The contents of settings.js are similar to:
$(function() {
setInterval(function() {
// auto-submit form every 10 seconds
$('form').submit();
}, 10000);
}
});
The problems
Certain javascript functions continue to run (e.g. setInterval) after the partial page that called them has been replaced by another.
This business of loading new javascript for each partial page feels messy; but for the life of me, I can't find any recommendations for best practices.
What is the better way to achieve this effect of dynamic partial-page loading/unloading while allowing page-specific scripts for each partial page?
Thank you!
Firstly...once you load javascript...you can't unload it
The setInterval problem will require using clearInterval
Declare some esoteric name that would make it fairly unique as a global variable when you initialize setiIterval; Make sure you declare the var outside of $(document).ready before using it
var my_super_form_submitter
$(document.ready)function(){...
my_super_form_submitter=setInterval(func.....
Then whenever you load a new page
if(my_super_form_submitter)
clearInterval(my_super_form_submitter)
As for collisions with other methods....you could adopt a content class protocol for your page specific code. On each page load, change class of content div...then use that class within selectors for jQuery
For first problem:
Question is what functions continues to run after replacing packages. SetInterval that you mentioned uses js timers, and simply replacing package wont stop timer automatically.
You should clear all timers started via setInterval before replacing.
E.g.
$(function() {
var timer = setInterval(function() {
// auto-submit form every 10 seconds
$('form').submit();
}, 10000);
}
function uninitialize(){
clearInterval(timer);
}
Just call uninitialize before replacing package, and it should work.
UnfortunatelyI don't know any proper way for loading partial pages, but I hope it helps you somehow (: