I have a Javascript function that creates a few list items in an unordered list when run, but when the page is called the onload event does not run the function, and it only works when I refresh the page. I tried putting an onclick function in the anchor tag that leads to the page, but that too does not run the function. I'm using JQuery mobile's UI to style and D3. I also tried .ready from JQuery, but that did not solve the problem either.
<div data-role="content">
<ul data-role="listview">
<li> To Data</li>
</ul>
</div>
The D3 function is:
coolcat: function(){
var AddedElem = d3.select("#YourData_ul").selectAll("li")
.data(lines)
.enter()
.append("li")
.attr("class", "ui-field-contain");
AddedElem.append("label").text(function (d){ return d.itemname;}).attr("class", "information");
AddedElem.append("input").attr("class", "input-deco");
console.log("Just ran Coolcat!");
I previously put the "Onload" event in the data.html file, (Not in the index), and it did not work, so I put it in the index, and it would not display either. (It did run without a refresh)
It's probably linked to the order of loading of these libraries.
You could avoid all that by using plain old JavaScript, which would look like this:
HTML:
<div data-role="content">
<ul id="myListView" data-role="listview">
<li> To Data</li>
</ul>
</div>
JavaScript:
var list = document.getElementById('myListView');
var listEntry = document.createElement('li');
listEntry.appendChild(document.createTextNode('new list text'));
list.appendChild(listEntry);
I haven't completed the rest of it, but if you call this javascript on your onload function, it'll definitely run.
You can also append your function to each of the list items using a standard DOM selector also.
Related
I'm a JavaScript novice and I'm having some difficulty getting my code to work. I've set up a function that pulls in variables based on element classes and IDs and executes it onclick.
<div id="holder">
<img id="wallImg" src="/testpath/selwall/nopaint.jpg">
</div>
<div id="options">
<ul id="selWall">
<li class="bluepaint" onclick="printStuff()"><strong>Blue</strong></li>
<li class="redpaint" onclick="printStuff()"><strong>Red</strong></li>
<li class="greenpaint" onclick="printStuff()"><strong>Green</strong></li>
</ul>
</div>
<script type="text/javascript">
function printStuff() {
var imgCategory = srcElement.parentNode;
var imgClass = srcElement.className;
document.getElementById("wallImg").src="http://testurl.co.uk/media/gbu0/" + imgCategory + ImgClass + ".png";
}
</script>
The user is supposed to be able to select their paint colour from a selection of swatches (the ul#selWall li elements) and the JS will change the source of a particular image ID on the page (in this case, img#wallImg) with the clicked element's class and clicked element's parent element ID.
Eventually I want to be able to expand this script to use the ul id as a URL parameter name and the paint type (i.e. testurl.com/paint-selection&selWall=bluepaint&selDoor=greenpaint.) As far as I know, JQuery is unable to append URLs so I'd rather stick with plain JavaScript.
You're saying you want to stick with javascript because you don't think jQuery can append URLs. This is not a real reason to just entirely ignore it. JQuery IS javascript, it's just a library. This means that you can just use vanilla javascript whenever you want it, for example, when you want to change the URL.
Now for your desired functionality. You can use the keyword this in your inline click event registrator (i.e. onclick="printstuff()"). Passing the this variable will allow you to use the clicked element in the click handler. So change onclick="printStuff()" to onclick="printStuff(this)". Now in your function you can just use this instead of srcElement, and make sense.
OR INSTEAD USE JQUERY LIKE THE REST OF THE WORLD
$(document).ready(function(event){
$("#selwall).children("li").on("click", function(event) {
event.preventDefault();
var category = "sellwall"; //probably want to store this into a data-category arrtibute somewhere (maybe in the id=sellwall ul)
var imgClass = $(this).attr('class'); //preferably use data-img_id or something too (i.e. dont use classes and id's to store data you need somewhere else).
$("#wallImg").attr('src', <url> with imgClass and category>);
});
})
So I'd recommend using jQuery (since you're a javascript novice too, dont learn bad stuff, just learn how to program well right away) and using the data-attribute paradigm, look it up on the internet. Use it to store the URL parts you want to use.
Made some changes to your script to make script work and get the parent id and class of the current element.
function printStuff(srcElement) {
var imgCategory = srcElement.parentNode;
var imgClass = srcElement.className;
document.getElementById("wallImg").src="http://testurl.co.uk/media/gbu0/" + imgCategory.getAttribute('id') + imgClass + ".png";
alert(document.getElementById("wallImg").src);
var url = 'testurl.com/paint-selection&selWall='+imgClass+'&selDoor='+ imgCategory.getAttribute('id');
alert(url);
}
<div id="holder">
<img id="wallImg" src="/testpath/selwall/nopaint.jpg">
</div>
<div id="options">
<ul id="selWall">
<li class="bluepaint" onclick="printStuff(this)"><strong>Blue</strong></li>
<li class="redpaint" onclick="printStuff(this)"><strong>Red</strong></li>
<li class="greenpaint" onclick="printStuff(this)"><strong>Green</strong></li>
</ul>
</div>
I'm working on a site which will be maintained by not so tech savvy people, and I need to be able to give them the ability to add "see-more" anchors which use Jquery slide up/down to reveal their content.
My code works well for a single instance of the read more, but when there are multiple instances of this, it gets fairly screwed up.
javascript/jquery
$(".see-more").nextUntil(".see-less").wrapAll("<div class='see-more-content'></div>");
$(".see-less").hide();
var count= 1
/*
$(".see-more-content").each(function(){
var count= count+1;
$(this).data("count",count);
console.log(count);
});
*/
$(".see-more-content").slideUp(0);
$(".see-more").click(function(){
$(".see-more-content").slideToggle();
$(".see-more").hide();
$(".see-less").show();
});
$(".see-less").click(function(){
$(".see-more-content").slideToggle();
$(".see-less").hide();
$(".see-more").show();
});
HTML
<a class="see-more">See More...</a>
<ul>
<li>Advanced Elastic search Technology </li>
<li>Document Text Search</li>
<li>Embed Code Web Publishing for Images, Video & PDFs</li>
<li>Video Management with HTML5 Full</li>
<li>Previews On the Fly Conversions and Transcoding</li>
<li>Print on Demand</li>
<li>Stylized Collections (Lightboxes/Galleries)</li>
<li>Alerts and Notifications</li>
<li>Comments, Ratings and Favorites</li>
<li>WordPress and Drupal CMS Integrations</li>
<li>Dropbox Integration</li>
<li>Asset Level Performance Analytics • Site Activity Analytics Dashboard</li>
<li>Unlimited Custom User Access Levels</li>
<li>Integrated Content Contribution and Workflow</li>
<li>Personal Profile Management</li>
<li>Mobile App and Site </li>
<li>Watermarking</li>
<li>Rights Management</li>
<li>All New Feature Releases3</li>
</ul>
<a class="see-less">See Less...</a></div>
What I want to happen:
I want everything between the anchor with class see-more and anchor with class see-less, to get wrapped in a div, which when the anchor for see-more is clicked that div jquery slides down, when see-more is clicked, and slides up when see-less is clicked.
What is happening:
It works perfect when there is only one instance of see-more and see-less in a page. https://jsfiddle.net/TheWebTech/by3LsLuu/
When there are multiple instances of see-more and see-less in the html, the contents of all see-more+see-less blocks after the first instance are all moved/wrapped into the first block instances of the see-more see-less blocks get added.
https://jsfiddle.net/TheWebTech/by3LsLuu/4/
How do I prevent everything from being wrapped into the first instance of the see-more see-less block and instead have each one get wrapped separately?
Bonus but not really required: how can I make each see-more section slide up/down separately from eachother?
If you're going to keep the layout the same, you can use .prev() and .next() jQuery methods to determine which selector group you're referring too. Here's an updated fiddle with two instances:
https://jsfiddle.net/szva79d6/1/
First, I've made it so that your wrapping function applies to each selector individually, like so:
$(".see-more").each(function() {
$(this).nextUntil(".see-less")
.wrapAll("<div class='see-more-content'></div>");
});
What I've done in the two event methods is to make each event only act on the previous or next siblings, so that your events are properly delegated to each dynamically wrapped element.
$(".see-more").click(function() {
var $more = $(this),
$content = $more.next(".see-more-content"),
$less = $content.next(".see-less");
$content.slideToggle();
$more.hide();
$less.show();
});
$(".see-less").click(function() {
var $less = $(this),
$content = $less.prev(".see-more-content"),
$more = $content.prev(".see-more");
$content.slideToggle();
$less.hide();
$more.show();
});
You need to target specific to itself, try this:
$(".see-more").click(function(){
$(this).next(".see-more-content").slideToggle(); // find next content and show
$(this).hide(); // hide the see more button
$(this).nextAll('.see-less').first().show(); // show the next see less button
});
$(".see-less").click(function(){
$(this).prev(".see-more-content").slideToggle();
$(this).hide();
$(this).prevAll(".see-more").first().show();
});
Here's an updated fiddle
Using JQuery mobile I want to add a ul-ListView to a window dynamically creating it via JScript, there is a problem.
When I add the ListView fixed to HTML, everything works fine. The definition looks like
...
<div data-role=content>
<ul id='listviewAktuelleChecklist' data-role=listview data-theme="d" data-divider-theme="d" data-inset=true>
<li id="listDividerAktuelleChecklist" data-role=list-divider>yyy Checklist</li>
<li id='LoadChecklist'> <a> Checkliste von Market-Value laden </a></li>
</ul>
</div>
...
and when showing in Firefox its just what was expected. But when I create it by JScript, it looks like that:
(sorry guys, I'm not allowed to add a picture here due to missing references, so heres a link to the picture:
http://www.market-value.de/downloads/ul.jpg
The top ListView is what I get via the HTML definition, below the "OK" button what was generated (for those who don't view the picture: the generated Listviw shows just as a normal HTML "ul" with bullets...)
I used that code:
$("#BTN1").bind ("click", function (event)
{
var html = "";
html += "<ul id='ChecklistListea' data-role=listview data-theme='d' data-divider-theme='d' data-inset=true>"
html += '<li id="listDividerAktuelleChecklista" data-role=list-divider>yyy Checklist</li>'
html += "<li id='LoadChecklista'> <a> Checkliste laden </a></li>";
html += "</ul>";
$(html).appendTo('#DivChecklistListe');
$("#ChecklistListe").listview("refresh");
});
I tried some different methods for creating the dynamic HMTL, but the result was always the same.
Does anyone knows, what is going wrong here?
ps: if I define the ListView in HMTL directly and only add the ListItems everything works fine!
First you are calling refresh on a wrong id, but even in case of a correct id this will not work. This is because you are creating a listview from scratch, ul element with inner li elements.
In this case it is not enough to call listview('refresh') because listview first must be initialized before it can be refreshed.
It can be done like this:
$("#ChecklistListea").listview().listview("refresh");
First .listview() call will initialize a listview and second one will style it.
Working example: http://jsfiddle.net/Gajotres/4HRNK/
I am creating a mobile app (Phonegap/Cordova 1.5.0, JQM 1.1.0) and testing on iOS 5.1. I have a list of items that the user "owns" or wants to own. Throughout the app, the user can edit their list by adding and removing items. Whenever items are added or removed, the list updates, and it is displaying fine, with all of the JQuery CSS intact except the corners are no longer rounded (I'm thinking because data-inset is getting set to "false").
Here is my html for the list-headers:
<div data-role="page" id="profile">
<div data-role="header" data-position="fixed">
<...>
</div><!-- /header -->
<div data-role="content" data-theme="a">
<...>
<ul id="user-wants-list" data-role="listview" data-inset="true" data-theme="d" data-dividertheme="d" >
</ul> <!--/Wants list-->
</br>
<ul id="user-haves-list" data-role="listview" data-inset="true" data-theme="d" data-dividertheme="d" >
</ul> <!--/Has list-->
</br></br>
</div> <!--/content-->
</div> <!--/Profile-->
And here is the Javascript where I remove the old list and dynamically add the new one (the parameter 'haves' is an array of objects):
function displayHaves(haves){
var parent = document.getElementById('user-haves-list');
removeChildrenFromNode(parent);
parent.setAttribute('data-inset','true');
$(parent).listview("refresh");
var listdiv = document.createElement('li');
listdiv.setAttribute('id','user-haves-list-divider');
listdiv.setAttribute('data-role','list-divider');
listdiv.innerHTML = "I Have (" + haves.length + ")";
parent.appendChild(listdiv);
//create dynamic list
for(i=0;i<haves.length;i++){
var sellListing = haves[i].listing;
var userInfo = haves[i].user;
var itemData = haves[i].item;
//create each list item
var listItem = document.createElement('li');
listItem.setAttribute('id','user-haves-list-item-'+i);
parent.appendChild(listItem);
var link = document.createElement('a');
link.setAttribute('id','user-haves-link-' + i);
new FastButton(link, function(listing) {
return function() { displaySellListingPage(listing); }
}(sellListing));
listItem.appendChild(link);
var link = document.getElementById('user-haves-link-' + i);
var pic = document.createElement('img');
pic.setAttribute('src',itemData.pictureURL);
pic.setAttribute('width','80px');
pic.setAttribute('height','100px');
pic.setAttribute('style','padding-left: 10px');
link.appendChild(pic);
var list = document.getElementById('user-haves-list');
$(list).listview("refresh");
}
}
and my function removeChildrenFromNode(parent) is as follows:
function removeChildrenFromNode(node){
while (node.hasChildNodes()){
node.removeChild(node.firstChild);
}
}
So my question is, why does the listview lose the data-inset attribute?
Or, equally valid: is there another way I could/should be achieving corner rounding besides "data-inset='true'"?
Here are things I have tried:
using .trigger("create") on both the listview and the page
adding the listview with explicit styling each time by using $("#page-ID").append(...)
I read another post on StackOverflow that said that JQM creates some inner elements when you create an item (this post had to do with dynamic buttons not being the right size), and that there are some classes (like .ui-btn) that you can access (that may be losing styling when I remove the children from the node?), but I was unable to make any headway in that direction.
Thanks in advance for the help!
I figured out the answer to my question, but not a solution (yet).
$(list).listview('refresh') was getting called on some elements before they had been put on the page, so it was essentially being called on nothing (or another way to think about it is that each list item being appended happens after the refresh call, so it overrides some of the visual styling).
I know the problem has to do with asynchronous loading in javascript. Essentially, the .listview('refresh) executes before the earlier code, which creates the elements but takes longer to execute. I understand the reasoning behind the design, but is there some way to get around this in this case?
I am thinking some conditional that I could set, like:
var doneLoading = false;
//Then when finished set doneLoading to 'true'
if(doneLoading) $(list).listview('refresh');
but if the refresh gets called first, I figure that doneLoading will just evaluate to false and then not execute once the list is actually done loading.
Is there any kind of onComplete callback I can use, or a way to make it happen synchronously?
Try calling listview(refresh) after updating the HTML.
I have dropdown-Lists which have a lot of elements (>1000). When I select one of those elements the dropdown has to be rebuild because the selection of one element can cause others to disappear. I solve this in code behind (asp.net). Showing and hiding that dropdown usually is done in several milliseconds.
But when I select an element the div has to be rebuild which takes up to 20 seconds which is no surprise as that div contains about 300KB of Data which have to be sent to the client. The DIV looks like this:
<div id="ctl00_PlaceHolderMain_ctlProductSelector_SubstancesList" class="substancesListWrapper">
<ul>
<li class='elementSingle'>(2-Propyloxy)ethyl acetate</li>
<li class='elementSingle'>[(2-Propenyloxy)methyl] oxirane</li>
<li class='elementSingle'>1-(2-Pyridyl) piperazine</li>
<li class='elementSingle'>1,1,1,2-Tetrachloro-2,2-difluoroethane</li>
<li class='elementSingle'>1,1,1,2-Tetrafluoroethane</li>
<li class='elementSingle'>1,1,1-Trichloroethane</li>
(etc.)
Now I wonder if there is a way to compress that div-String and decompress it client-side by jQuery or something like that to reduce traffic. Does that work and if yes: What percentage of bytes do I usually safe?
This all happens in a SharePoint-Site (which should not make any difference hopefully)
You might improve several things.
One would be to move all your JavaScript links into one.
This would save you 85 characters per row.
<li class='elementSingle'>(2-Propyloxy)ethyl acetate</li>
<li class='elementSingle'>[(2-Propenyloxy)methyl] oxirane</li>
Could become this
<li class='elementSingle'><a href='#3268'>(2-Propyloxy)ethyl acetate</a></li>
<li class='elementSingle'><a href='#2415'>[(2-Propenyloxy)methyl] oxirane</a></li>
...
And one jquery click handler:
jQuery("li.elementSingle a").click(function(){
__doPostBack('ctl00_PlaceHolderMain_ctlProductSelector_pnlSubstances', this.href.replace('#',''));
});
Another point would be to remove class='elementSingle' and add a id to your ul for css/js.
This would save 22 characters per row.
If you're using jQuery already, just remove the anchors completely and provide id attributes for the list item elements.
The use a jQuery selector that reads out the id.
HTML would look kinda like this...
<div id="ctl00_PlaceHolderMain_ctlProductSelector_SubstancesList" class="substancesListWrapper">
<ul>
<li class='elementSingle' id="ct100-3268">(2-Propyloxy)ethyl acetate</li>
<li class='elementSingle' id="ct100-2415">[(2-Propenyloxy)methyl] oxirane</li>
etc...
The jQuery could be something like this...
$(function() {
$('#ctl00_PlaceHolderMain_ctlProductSelector_SubstancesList .elementSingle')
.click(function() {
var number = $(this).attr('id').match(/-(\d+)$/)[1];
__doPostBack('ctl00_PlaceHolderMain_ctlProductSelector_pnlSubstances', number);
});
});
(disclaimer; above is untested, but should give you a decent indication. Post a jsfiddle example first if you want a tested example).
Alternatively, think about using AJAX to load the list after loading the rest of the page.