I'm looking to try and check if the hash in the url contains a certain value before proceeding, I have a function that works like so:
$(window).load(function () {
var hash = window.location.hash,
number = $(hash).index(),
width = 403,
final = width * number;
setTimeout(function () {
$('.news-inner-wrap').animate({
'marginLeft': "-=" + final + "px"
});
}, 1000);
});
So if the hash is www.website.com/#news-item-03 it will slide the user horizontally along to the 3rd news story, this works great!. I only want this function to fire though if the hash contains news-item obviously the number after each will change, but if the hash begins with news-item then I want the function above to be fired, I'm not even sure it this is at all possible, any suggestions would be greatly appreciated!
No need for jQuery, this should work nicely
if (window.location.hash) {
if (window.location.hash.indexOf('news-item') == 1) { // not 0 because # is first character of window.location.hash
// it's at the start
}
else if (window.location.hash.indexOf('news-item') != -1) {
// it's there, but not at the start
}
else {
// not there
}
}
Use a regular expression:
var matches = hash.match(/^#news-item-([0-9]+)$/);
if (matches) {
var number = matches[1];
// Rest of your code
}
Related
I am trying create a page that will run some given URLs, in time this will be a database populated list of URLs loaded into an array. I have it working using some code I have altered, however I don't want it to keep looping, I just want it to stop once the list is complete.
So basically loads first URL, waits .5 of a second after the pages loads, then moves onto the next until the list of URLS is finished.
However, my code keeps looping. How do I prevent this?
var urls1 =
[
'http://localhost:8500/SupportTools/t1.cfm',
'http://localhost:8500/SupportTools/t2.cfm',
'http://localhost:8500/SupportTools/t3.cfm',
'http://localhost:8500/SupportTools/t4.cfm',
'http://localhost:8500/SupportTools/t5.cfm'
];
function showUrl1(idx)
{
var f1 = document.getElementById("f1");
f1.onload = function()
{
var next = ++idx % urls1.length;
setTimeout(function()
{
showUrl1(next);
}, 500);
}
f1.src = urls1[idx];
}
function start()
{
showUrl1(0);
}
<iframe class="show1" id="f1" src="about:blank"></iframe>
The reason it's looping is because you're using the remainder operator %. Just check the to see if next is greater than or equal to the length and then don't call setTimeout(). I've changed the snippet so that you can see it output in the console but you should get the idea.
var urls1 = [
'http://localhost:8500/SupportTools/t1.cfm',
'http://localhost:8500/SupportTools/t2.cfm',
'http://localhost:8500/SupportTools/t3.cfm',
'http://localhost:8500/SupportTools/t4.cfm',
'http://localhost:8500/SupportTools/t5.cfm'
];
function showUrl1(idx) {
if (idx >= urls1.length) {
return;
}
console.log(urls1[idx]);
var next = ++idx;
setTimeout(function() {
showUrl1(next);
}, 500);
}
function start() {
showUrl1(0);
}
start();
Dont showUrl when the list ends
function showUrl1(idx)
{
var f1 = document.getElementById("f1");
f1.onload = function()
{
var next = idx === urls1.length? null: ++idx ;
setTimeout(function()
{ if(next != null){
showUrl1(next);
}
}, 500);
}
f1.src = urls1[idx];
}
I am developing MVC 5 application in which I want to display all related images in time interval of 2 sec. Image path is stored in Database. I know that I can use setInterval javascript function for the same. I am able to loop through first two image (index is hard-coded), however want to display all images one by one
Below is my jquery for the same. Please let me know how i can set index dynamically
$(document).ready(function () {
var curImg = 0;
setInterval(function () {
var path = '#Model.lstImage[1].image_path'
$('#memImg').attr("src",path);
}, 2000);
You need to create a array of image links from your model first and then use it in the set interval. use this logic.
Put this in your view.
#{
var imageLinks = #Model.lstImage.Select(x => x.image_path).ToList();
}
Now we have the list of imageLinks. let use this in Jquery
Add this logic in your script
var imageArray = #Html.Raw(Json.Encode(imageLinks)); // assign the c# variable data into jquery variable.
$(document).ready(function () {
var curImg = 0;
var index = 0;
setInterval(function () {
if(index > imageArray.length){
index = 0; // set back index to zero when the last index is reached.
}
var path = imageArray[index];
$('#memImg').attr("src",path);
index++; //increment the index for next image display.
}, 2000);
});
Note that image paths are available at server-side (in your ViewModel) but switching is made at client side (with setInterval). Now you have (at least) two options:
1) Save whole list in a JavaScript array, setInterval() callback will then simply loop through it.
<script type = "text/javascript">
var currentImage = 0;
var images = #("[" + String.Join(",", Model.lstImage.Select(x =>
String.Format("\"{0}\"", HttpUtility.JavaScriptStringEncode(x.image_path)) + "]");
$(document).ready(function () {
setInterval(function () {
currentImage = (currentImage === images.length - 1) ? 0 : currentImage + 1;
document.getElementById("memImg").src = images[currentImage];
}, 2000);
});
</script>
One note about C# array to JavaScript array: do not use (even if it's widely encouraged, also here on Stack Overflow) Json.Encode(). Escaping rules for JavaScript and for JSON are different, there is a small intersection but a valid JSON string may be not a valid JavaScript string. For example / may be escaped in JSON as \/ but in JavaScript it's an invalid escape sequence (even if most browsers accept it). Think about: http://www.example.com/images/01.png, it doesn't matter what Json.Encode() actually does, it may change its behavior still respecting its interface (encoding an object as valid JSON string...)
2) Do not save image URLs in your ViewModel, just its length. Client side JavaScript code will then query server using (for example): http://www.example.com/images/1 and your controller method will resolve image from its ID and return it with File() or writing directly into response stream.
<script type = "text/javascript">
var currentImage = 0, imageCount = #Model.lstImage.Count;
$(document).ready(function () {
setInterval(function () {
currentImage = (currentImage === imageCount - 1) ? 0 : currentImage + 1;
document.getElementById("memImg").src =
#Url.Action("Read", "Images") + "?id=" + currentImage;
}, 2000);
});
</script>
With this controller method:
public class ImagesController : Controller {
public ActionResult Read(int id) {
return ... // your code here
}
}
I have a search filter that hides s as the user enters text into a form input. I need it to be dynamic, so that as the user changes their input, the filter refreshes. I accomplished this by having the filter clear on every keyup, but that causes the filter to be delayed and to flash when a word is typed quickly into the filter. You can see what I mean here:
http://cambridgefellows.com/directory-of-fellows/
Here is my jquery:
$(document).ready(function() {
$('input[name=searchFilterInput]').val('');
$('input[name=searchFilterInput]').keyup(function() {
var searchFilterVal = $('input[name=searchFilterInput]').val();
searchFilterVal = searchFilterVal.replace(/ /g, '-');
searchFilterVal = searchFilterVal.toLowerCase();
$('tr.hide').fadeIn('slow').removeClass('hide');
if(searchFilterVal == '') {
$('tr.hide').fadeIn('slow').removeClass('hide');
} else {
$('tr.fellows').each(function() {
var pattern = $(this).attr('class'); // the pattern to be matched
var match = pattern.match(searchFilterVal);//If pattern matches it returns the match
if(!match) {
$(this).fadeOut('normal').addClass('hide');
} else {
}
});
}
});
$('#searchForm').bind("keyup keypress", function(e) {
var code = e.keyCode || e.which;
if (code == 13) {
e.preventDefault();
return false;
}
});
});
I think there must be an easier way to handle this so that the filter dynamically updates as the user enter or alters their search text. Can someone more experienced than me look at this an enlighten me to the obvious thing that I'm overlooking? Thank you so much for your help.
Looks like you need a setTimeout and clearTimeout.
var timer;
$('input[name=searchFilterInput]').keyup(function() {
clearTimeout(timer);
timer = setTimeout(function() {
var searchFilterVal = $('input[name=searchFilterInput]').val();
searchFilterVal = searchFilterVal.replace(/ /g, '-');
searchFilterVal = searchFilterVal.toLowerCase();
$('tr.hide').fadeIn('slow').removeClass('hide');
if(searchFilterVal == '') {
$('tr.hide').fadeIn('slow').removeClass('hide');
} else {
$('tr.fellows').each(function() {
var pattern = $(this).attr('class'); // the pattern to be matched
var match = pattern.match(searchFilterVal);//If pattern matches it returns the match
if(!match) {
$(this).fadeOut('normal').addClass('hide');
} else {
}
});
}
}, 300);
});
That way whenever a user hits the next key, the timeout will be cleared from the previous keypress and the code will only execute for the current keypress.
Reduce the milliseconds if you feel it's not updating fast enough.
I have the following to try to reload on a connection drop:
setInterval(window.location.reload(), 1000);
My concern with this is that it could continue forever, ddos'ing my application.
How can I update the above to try at max 20 times before giving up and breaking?
Thank you
This makes me feel dirty, but you could update/extract the window hash with each refresh:
function hack () {
var last = parseInt(location.hash.slice(1));
if (last < 20) {
window.location.hash = last + 1;
window.location.reload();
}
}
window.location.hash = 0;
setTimeout(hack, 1000);
You need to persist some counter state from one page load to the next so you can know when 20 reloads have been done. Your options are:
A hash value
A query parameter
A cookie value
Something stored in local storage
If you don't need this value to persist beyond just the reloads of this page, then options 1) and 2) are better as they are only as persistent as you need. A hash value will not be sent to your server, but could interfere with other uses of the hash value. A query parameter would be sent to the server, but any reasonable server will ignore query values it doesn't know and it won't interfere with anything else. I'd probably pick a query parameter and have actually used one to avoid infinite redirection loops in some of my code. You could implement option 2) like this:
function checkAutoReload() {
var currentCnt = 0;
var re = /(\?|&)(reloadCnt=)(\d+)/;
var param = window.location.search.match(re), newURL;
if (param) {
currentCnt = parseInt(param[3], 10);
newURL = window.location.href.replace(re, "$1$2" + (currentCnt + 1))
} else {
newURL = window.location.href;
newURL += window.location.search ? "&" : "?";
newURL += "reloadCnt=1";
}
if (currentCnt < 20) {
window.location.replace(newURL);
}
}
setTimeout(checkAutoReload, 1000);
Notice, there's no need for a setInterval() because a given page's code only runs once before it either reloads or finds that it is done reloading.
Store the reloadCount in localStorage
MDN DOM Storage
var maxReload = 20;
var reloadPage = function() {
if (typeof a !== "undefined" && a !== null) {
console.log(localStorage.reloadCount);
localStorage.reloadCount = 0;
};
var reloadCount = parseInt(localStorage.reloadCount, 10);
console.log(reloadCount);
if (reloadCount < maxReload) {
reloadCount += 1;
localStorage.reloadCount = reloadCount;
// RELOAD CODE HERE
};
};
// call reloadPage from your code
reloadPage();
I am trying to make a bookmarklet that when clicked will check the URL of the current tab/window to see if it contains 'char1' and/or 'char2' (a given character). If both chars are present it redirects to another URL, for the other two it will append the current URL respectively.
I believe there must be a more elegant way of stating this than the following (which has so far worked perfectly for me) but I don't have great knowledge of Javascript. My (unwieldy & repetitive) working code (apologies):
if (window.location.href.indexOf('char1') != -1 &&
window.location.href.indexOf('char2') != -1)
{
window.location="https://website.com/";
}
else if (window.location.href.indexOf('char1') != -1)
{
window.location.assign(window.location.href += 'append1');
}
else if (window.location.href.indexOf('char2') != -1)
{
window.location.assign(window.location.href += 'append2');
}
Does exactly what I need it to but, well... not very graceful to say the least.
Is there a simpler way to do this, perhaps with vars or a pseudo-object? Or better code?
A (sort-of) refactoring of dthorpe's suggestion:
var hasC1 = window.location.href.indexOf('char1')!=-1
var hasC2 = window.location.href.indexOf('char2')!=-1
var newLoc = hasC1
? hasC2 ? "https://website.com/" : window.location.href+'append1'
: hasC2 ? window.location.href+'append1' : '';
if (newLoc)
window.location = newLoc;
Calling assign is the same as assigning a value to window.location, you were doing both with the addition assignment += operator in the method anyway:
window.location.assign(window.location.href+='append2')
This would actually assign "append2" to the end of window.location.href before calling the assign method, making it redundant.
You could also reduce DOM lookups by setting window.location to a var.
The only reduction I can see is to pull out the redundant indexof calls into vars and then test the vars. It's not going to make any appreciable difference in performance though.
var hasChar1 = window.location.href.indexOf('char1') != -1;
var hasChar2 = window.location.href.indexOf('char2') != -1;
if (hasChar1)
{
if (hasChar2)
{
window.location="https://website.com/";
}
else
{
window.location.assign(window.location.href+='append1');
}
}
else if (hasChar2)
{
window.location.assign(window.location.href+='append2');
}
Kind of extendable code. Am i crazy?
var loc = window.location.href;
var arr = [{
url: "https://website.com/",
chars: ["char1", "char2"]
}, {
url: loc + "append1",
chars: ["char1"]
}, {
url: loc + "append2",
chars: ["char2"]
}];
function containsChars(str, chars)
{
var contains = true;
for(index in chars) {
if(str.indexOf(chars[index]) == -1) {
contains = false;
break;
}
}
return contains;
}
for(index in arr) {
var item = arr[index];
if(containsChars(loc, item.chars)) {
window.location.href = item.url;
break;
}
}
var location =window.location.href
if (location.indexOf('char1')!=-1 && location.indexOf('char2')!=-1)
{window.location="https://website.com/";}
else if (location.href.indexOf('char1')!=-1) {window.location.assign(location+='append1');}
else if (location.indexOf('char2')!=-1) {window.location.assign(location+='append2');}