I'm trying to design a site (possibly to make into a Chrome extension) that will allow me to mark which characters have done which events in an online game I play. I'd love it if I had the option to save the values of the checkboxes between visits (and ideally, character names as well), but I'm not great at coding. Also, I'd strongly prefer it if this information could be saved/cleared/reloaded on command, and not otherwise.
The page in question, please pardon me if my code isn't efficient or attractive. I actually prefer to work with it a bit more bunched up, but I tidied it for your benefits.
There had been a suggestion here that I was trying to work with:
var i, checkboxes = document.querySelectorAll('input[type=checkbox]');
function save() {
for (i = 0; i < checkboxes.length; i++) {
localStorage.setItem(checkboxes[i].value, checkboxes[i].checked);
}
}
function load_() {
for (i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = localStorage.getItem(checkboxes[i].value) === 'true' ? true:false;
}
}
But while it works fine in the test, it won't work when I put it into my document (you'll see the var i at the top still, the rest of the code I'd put above the reset function).
Help?
This line:
var i, checkboxes = document.querySelectorAll('input[type=checkbox]');
is in the head of your document and runs immediately. None of the checkboxes exist at the time that it runs.
I'd suggest putting that script at the end of your body element or placing it in a window.onload = function() {}.
If you inspect the DOM structure in the working jsFiddle link you posted, you'll see it places the script at the end of the body element.
Related
I'm trying to modify some code for dragging out files from your browser window I found here:
http://www.thecssninja.com/javascript/gmail-dragout
In my code I want to use for loops so I can handle a large number of files without repeating code over and over.
This is what I have:
file0
file1
file2
file3
<script type = "text/javascript>
var file_count = 3;
var fileDetails = [];
var files = new Array(file_count);
for(var i=0; i<=file_count; i++) {
files[i] = document.getElementById(i);
}
if(typeof files[0].dataset === "undefined") {
for (i=0; i<=file_count; i++) {
fileDetails[i] = files[i].getAttribute("data-downloadurl");
}
}else {
for (i=0; i<=file_count; i++) {
fileDetails[i] = files[i].dataset.downloadurl;
}
}
//I'm pretty sure the problem starts here.
//If you substitue i for a specific element from the array and comment out the for loop, the script works just fine for the element specified.
for(i=0; i<=file_count; i++) {
files[i].addEventListener("dragstart",function(evt){
evt.dataTransfer.setData("DownloadURL",fileDetails[i]);
},false);
}
I'm fairly certain the problem starts where I have it labeled, I'm not sure why there is a problem or how to solve it.
Some things I should point out:
This only works in Chrome. This is not an issue for me.
I want this to handle 20+ files.
The problem does indeed start where you think it does
//I'm pretty sure the problem starts here.
//If you substitue i for a specific element from the array and comment out the for loop, the script works just fine for the element specified.
for(i=0; i<=file_count; i++) {
files[i].addEventListener("dragstart",function(evt){
evt.dataTransfer.setData("DownloadURL",fileDetails[i]);
},false);
}
Basically your dragstart event listener is bound to i, which at the time of execution is the last element in the list.
The following will work better.
//I'm pretty sure the problem starts here.
//If you substitue i for a specific element from the array and comment out the for loop, the script works just fine for the element specified.
for(i=0; i<=file_count; i++) {
files[i].addEventListener("dragstart", (function(idx) {
return function(evt){
evt.dataTransfer.setData("DownloadURL",fileDetails[idx]);
}
})(i),false);
}
In the above code you will be creating and returning an object of type function with the correct value of i bound - essentially the closure is created at a different level and thus when accessed will get the correct data.
I have about 20 pages of forms and I need all the inputs on every page to be converted to uppercase. I'm wondering if it would be possible to build a JavaScript function that I could just copy/paste onto every page without having to do it individually on each input on every page.
Maybe using getElementsByTagName() and addEventLister() and toUpperCase().
Would something like this work?
PS. using CSS only works until the browser send the information back to the server, so that's out.
Something like this should get you started:
var inputElements = document.querySelectorAll('input, select, textarea');
for (var i = 0, l = inputElements.length; i < l; i++) {
if (inputElements[i].tagName == 'SELECT') {
inputElements[i].options[inputElements[i].selectedIndex].value = inputElements[i].options[inputElements[i].selectedIndex].value.toUpperCase();
} else {
inputElements[i].value = inputElements[i].value.toUpperCase();
}
}
Although you should really reconsider this and just do it serverside.
Demo: http://jsfiddle.net/ZgrqA/
I need to write a Javascript function that run from Master page, to find a ModalPopup in the contenct page and close it. Following code works, but not what I want. I need use something like mpeEditUser.ClientID, but I got an error. Also, it would be nice if I could find a ModalPopup without knowing its id, by its type (ModalPopupExtender) instead. Any suggestion?
function CloseModalPopup() {
var mpu = $find('ctl00_ContentPlaceHolder1_mpeEditUser');
mpu.hide();
}
Here is my solution: (If you see any problem, please let me know. Thanks)
I get the ModalPopup id in the codebehind, and pass it to my javascript function.
In the Page_Load of the default.master.cs:
ContentPlaceHolder cph = (ContentPlaceHolder)FindControl("ContentPlaceHolder1");
string sMpeID = (AjaxControlToolkit.ModalPopupExtender)cph.FindControl("mpeEditUser");
In my Javascript function:
var mpe = $find('<%=sMpeID%>');
if (mpe != null) {
mpe.hide();
}
Its likely the tag is getting mucked up by being called through another page, this happened to me. I don't know the best fix for you, however the way I addressed the issue was to first find the mpe through a javascript function that looked for a vague match out of all of the elements on the page.
var elemets = document.getElementsByTagName("*");
var mpe;
for (var i = 0; i < elemets.length; i++) {
var id = elemets[i].id
if (id.indexOf("mpe") >= 0) {
mpe = elemets[i];
}
}
If you have more then one mpe on the page you may want to match more if the string. For me the elements function only returned about 50 elements, so it was not too much overhead. That may not be the case for you, but even if you dont use this function in the final product it will assist you in discovering the actual ID of the elment.
I've been beating my head against the wall for a bit as I know the answer is simple but it eludes me. I have some programming experience but mainly with PHP. I came across an instance in which a site I am working on needed a script to automatically detect external links and open them in a new window. I found 2 separate javascript codes and they work beautifully but the problem is where there is an anchor tag such as href="#B" the code considers this an external link. I've done significant research and tried doing an indexOf and endWith() functions but neither are ignoring a link that has a #letter (i.e. #B).
Would be great if I could get some further assistance or pointers. See the code below I found on the net:
assigntarget:function(){
var rexcludedomains=new RegExp(this.excludedomains.join("|"), "i")
var all_links=document.getElementsByTagName("a")
if (this.mode=="auto" || (this.mode=="manual" && this.togglebox.checked)){
for (var i=0; i<=(all_links.length-1); i++){
if (all_links[i].hostname.search(rexcludedomains)==-1 && all_links[i].href.indexOf("http:")!=-1)
all_links[i].target=ddwindowlinks.linktarget
}
}
else{
for (var i=0; i<=(all_links.length-1); i++)
all_links[i].target=""
}
Now I've tried using index as I mentioned above to find if # exists in the link as below:
for (var i=0; i<=(all_links.length-1); i++){
if (all_links[i].hostname.search(rexcludedomains)==-1 && all_links[i].href.indexOf("#") ==-1 && all_links[i].href.indexOf("http://") !=-1)
all_links[i].target=ddwindowlinks.linktarget
Thanks for any help or potiners.
You could always just strip out the anchor tag
var str = str.replace(/#.*$/, "")
and test against that. I'd be interested to see exactly what this.excludedomains.join("|") equals and which exact links it fails against, though.
I'm using jquery to add elements to a blank list.
on the page I have:
<ul id="myList">
</ul>
and I go through a loop like this in the script that's called from a dynamically created event handler. (It's "onDrop" of a list item having been sorted with a drag operation)
var myListItemHTML;
for (var i = 0 ; i < 5 ; i++)
{
myListItemHTML += '<li id=listItem'+i+'>This is item number'+i+'</li>';
}
$('#myList').append(myListItemHTML);
and if I check after...
if ($('#myList li').length == 0 )
{
alert('Going to crash now since I'm expecting list items')
}
roughly 95% of the time the list is populated, but about 5% of the time I hit my alert that's going to cause an exception later.
Has anyone run into this? Is there a callback or way to know when/if the append really happens?
var myListItemHTML;
for (var i = 0 ; i < 5 ; i++)
{
$('#myList').append('<li id=listItem'+i+'>This is item number'+i+'</li>');
}
Try just appending inside the for loop.
if ($('#myList li').length == 0 )
{
alert('Going to crash now since I\'m expecting list items')
}
You need a \ before the ' so it doesn't conflict.
edit: jsfiddle that shows "undefined" http://jsfiddle.net/gyEre/1/
This is a bit of a longshot, because I'm making an assumption about your code beyond what was posted. Here goes:
I had a problem with some code once, which worked perfectly in all Browsers except Chrome, wherein it would fail randomly and seemingly without cause.
My problem, ultimately, was that Chrome was actually executing my JavaScript too fast, and that it was throwing off some of the timing in some of the AJAX calls that were being made earlier.
My code was such that AJAX event A triggered, which then passed data to AJAX event B. In Chrome only, though, I found that event B was on occasion occurring before event A, and that was the error condition.
If I recall, I think the solution was to force one key AJAX request to be made synchronously, though that should be used with care. Please see: http://api.jquery.com/jQuery.ajaxSetup/
I hope that's not too vague to be helpful. Good luck!
What I've learned is that I can't trust jquery for DOM manipulation called through dynamically created events. I welcome someone to prove me wrong, but this approach:
addListItem = function (itemID, itemText)
{
var li = document.createElement('li');
li.setAttribute("id", itemID);
var liText = document.createTextNode(itemText);
li.appendChild(goalTextNode);
document.getElementById('myList').appendChild(li);
}
for (var i = 0 ; i < 5 ; i++)
{
addListItem('listItem'+i, 'Item Text'+i);
}
will work 100% of the time and never fail.
In my experience, if the script in which the prepend function is used in the -tag, it will not work because the script is loaded before the DOM is ready.
To avoid this kind frustration, is a good habit to place your javascript before the tag.