Unable to create multiple versions of a DIV - javascript

I have some jQuery code, below, that tries to place multiple folder icons at the top of a gallery pane. The AJAX call retrieves the folder information which is just a string that looks like:
"boots,50,120,socks,50,160,shoes,50,200,"
where, in this case, there are three folders: "boots" located at top=50, left=120, socks etc.
For each folder in the returned data the code tries to create a div, containing a folder icon, position it according to the data from the AJAX call and append it to the DOM. But something is very wrong because I'm producing multiple multiple folders with the same name and same offset.
$.post('ajax.php', {op : 'get_folders'},
function(responseTxt, statusTxt, xhr) {
var folderDiv;
var folders = responseTxt.split(",");
for (i=0; i<folders.length; i=i+3){
name=folders[i];
posTop=folders[i+1];
posLeft=folders[i+2];
folderDiv = '<div class=openclosed_folder_icon>' +
'<img class="folder_icon" src="images/folder_closed.png" alt="closed folder" />' +
'<div class="folder_name" >name</div>' +
'</div>';
$(folderDiv).find('.folder_name').text(name);
$(folderDiv).attr({'id' : name});
$(folderDiv).draggable(folder_icon_dragOps)
.css({'cursor' : 'pointer',
'position' : 'absolute',
'top' : posTop,
'left' : posLeft
})
.appendTo('#galleryHeader');
}
});
Does anyone see a problem with this code?

Every time you do $(folderDiv), you are re-creating the DOM element and making a new jQuery object. You need to call $(folderDiv) once, and save it into a variable.
var folderDiv = '<div class=openclosed_folder_icon>' +
'<img class="folder_icon" src="images/folder_closed.png" alt="closed folder" />' +
'<div class="folder_name">'+name'+</div>' +
'</div>';
var $folderDiv = $(folderDiv); // Convert this into a DOM element, and save the jQuery object
// Do actions on the saved jQuery object, so that you are editing the *same* DOM element
// You can chain together these calls
$folderDiv.find('.folder_name').text(name).attr({'id' : name});
$folderDiv.draggable(folder_icon_dragOps).css({
'cursor':'pointer',
'position': 'absolute',
'top': posTop,
'left': posLeft
}).appendTo('#galleryHeader');

Related

lightgallery does not work with dynamically generated elements

I have implement lighgallery plugin to my local site... and this is not working with dom elements ...
for example
1.) append dom element created with js to html code..
if i create something like this in js "<span id='imgcon'><img src="image"></span>" and this all code is in a varialbe lets call galleryview (var galleryview) and this variable i append to a div that is in html file <html><head></head><bdy><div class="container"></div></bdy></html> and append like this from js file code $(".container").append(galleryview); and in end i use this $(".imgcon").lightGallery(); does not work...
Here is jsfiddle demo not working with dom
2.) images are in html code
i have html code smthing like this <html><head></head><bdy><div class="container"><span class="imgcont"><img src="image"></span></bdy></html>
This works fine as it.$(".imgcon").lightGallery();
Here is jsfiddle working demo without dom.
Question : why i cannot use dom with lightgallery ?
First demo is not working becasue i use js dom and second demo is working because i use html code in html file.. or there any problem with my code..
Simply put your $(".imagecontiner").lightGallery(); inside the click handler
http://jsfiddle.net/o0y70kv0/1/
The above will work only for the first dynamically created gellery.
To make it work for multiple elements: pre-create in-memory appendable elements and assign to each the .lightGallery() instance
http://jsfiddle.net/o0y70kv0/6/
$(document).ready(function() {
var imagesarray = [
"http://www.planwallpaper.com/static/images/Winter-Tiger-Wild-Cat-Images.jpg",
"http://www.gettyimages.ca/gi-resources/images/Homepage/Category-Creative/UK/UK_Creative_462809583.jpg",
"http://blog.jimdo.com/wp-content/uploads/2014/01/tree-247122.jpg",
"http://i765.photobucket.com/albums/xx291/just-meller/national%20geografic/Birds-national-geographic-6873734-1600-1200.jpg",
"http://www.gettyimages.com/gi-resources/images/CreativeImages/Hero-527920799.jpg"
];
var hiddenimages = "",
albumcover;
$("#appendnewcontainer").click(function() {
$("<span />", {
class : "container",
appendTo : $("#fotoappendarea"),
append : $("<span />", {
class : "imagecontiner",
html : "<a class='dfed' href=" + imagesarray[1] + "><img src='" + imagesarray[1] + "' class='_34'/></a>"
}).lightGallery()
});
});
});
when you generated gallery item after than you need to use below code in your project
var $methods = $('#gallery-container');
$methods.lightGallery();
$methods.data('lightGallery').destroy(true);
$methods.lightGallery({
thumbnail: true,
animateThumb: true,
showThumbByDefault: true,
});

How can I access the attributes of an element cloned via jquery within a javascript function?

I need to permit my users to dynamically create new categories and then branches and sub-branches within categories. To facilitate this I've built an html table that contains multiple nested tables. Each nested table is surrounded by its own div. The base category displays on the left and branches and sub-branches grow out to the right.
To allow the user to create the branches I call jquery clone() within a javascript function. Like this:
function elementCopy(targetTable, targetDiv)
{
var clone = $('.' + targetTable).clone(true).appendTo($("." + targetDiv));
}
This creates the requested clone and places it in the correct table. But I have not discovered how to access the clone's attributes to edit them.
In a previous iteration of this functionality, I called jquery clone() from within document.ready().
$('button[name="newTasks"]').click(function()
{
//Create the cloned block and keep the event listener so the newly displayed plus icon
// also creates a new block.
var clone = $(".tasksTable").eq(0).clone(true).appendTo(".tasksDiv");
//
clone.find( ".tasksTable" ).attr('name', 'Tasks' + '_' + countTaskBlocks);
});
I abandoned this iteration because I was unable to send parameters to the document.ready() version. Without the parameters, I could not position the clone within its proper table and sub-table. However, this version DID allow me to edit the clone's attributes.
This line edits all of the elements with the same class name:
$('.' + targetTable).attr('class', 'tasksTable' + '_' + countTaskBlocks);
How can I edit the 'name', 'id', and 'class' attributes of the specific clone created in the call to 'elementCopy' function?
JQuery methods are chainable, so you can do something like this.
function elementCopy( targetTable, targetDiv ) {
var clone = $( '.' + targetTable )
.clone( true )
.appendTo( $( "." + targetDiv ) )
.attr( {
'name': 'Tasks' + '_' + countTaskBlocks,
'id': 'Tasks' + '_' + countTaskBlocks,
'class': 'Tasks' + '_' + countTaskBlocks
} );
return clone;
}
Check out the demo below.
$('a').clone( true ).appendTo( $('body') ).attr( { 'class': 'Goodbye', 'href': 'http://www.example.com' } );
a::before { margin-right: .5em; content: attr(href); } a::after { margin-left: .5em; content: attr(class); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a class="hello" href="#">Link</a>
Search the children of the DIV you appended the clone to by the class name of the element you cloned.

How to retrieve id from selected item using "this"

I am new at jQuery/javascript. I tried some suggestions I found on this forum but so far it did not help.
THis is what I am trying:
When loading categories from a database ( using ajax) this HTML statement is added for each category:
$("#Links ul").append('<li id=\"cat' + i + '" data-catid=' + i + '>' + categorie_tekst[1] + '</li>');
Using F12 I see that the lines are correctly added.
E.g. <li id="cat3" data-catid="3">Seafood </li>
Next step is selecting a category in the screen and retrieve the products of this category using the value set for data-catid.
I have been told that I could "this.id" but so far no luck. Displaying the value of this.id with alert returns the correct value but for some reason I can't use it.
When I add (#cat3).attr(“data-catid”) in the code it works. But different options like these did not work:
("#cat"+ this.id).attr(“data-catid”)
(this).attr(“data-catid”)
var x = $(this).id();
var rest = x.substr(4, 1);
Everything with "this" creates error : Uncaught TypeError: ("#cat" + this.id).attr is not a function...
Trying to display any of these options does not give any output (not even a popup when I set an alert)
Any help would be appreciated!
You are loading dynamic values. Please use Event Delegation. And the $.one() binds the event once.
You need to add this in your ready function.
$(document).ready(function () {
$("#Links ul").one("click", ".cat", function(){
alert($(this).data('catid'))
});
});
To get the IDs of the elements, use $(this).attr("id") or $(this).prop("id") (latest jQuery) instead of this.id, as sometimes, it might return the jQuery object.
As you are creating elements like
$("#Links ul").append('<li class="cat" id=\"cat' + i + '" data-catid=' + i + '>' + categorie_tekst[1] + '</li>');
create elements using jQuery
$("#Links ul").append( $('<li></li>', {
class: "cat",
id: "cat" + i,
data-catid: i,
text: categorie_tekst[1]
});
As you are creating elements dynamically use Event Delegation. You have to use .on() using delegated-events approach.
$(document).ready(function () {
$("#Links ul").on(event, ".cat", function(){
alert($(this).data('catid'))
});
});

Recommended method of adding/storing/constructing HTML controls dynamically

Is there a recommended method of dynamically adding/storying/constructing HTML controls to dynamically added elements on a HTML page?
Basically, I have a widget based system I'm working on, where the user chooses the widgets s/he wants to have displayed. S/He can have as many or as little widgets on the screen as required, and they can also have the same widget many times displayed at once.
The script for that looks something like this:
success: function( widget_shell )
{
if( widget_shell.d[0] ) {
$(".column").empty();
var i = 0;
for ( i = 0; i <= widget_shell.d.length - 1; i++ ) {
var $widget = $("<div class='widget widget_" + widget_shell.d[i].widget_id + "'>").appendTo( $(".column_" + widget_shell.d[i].column_id) );
$("<div class='widget_header widget_header_" + widget_shell.d[i].widget_id + "'>").appendTo( $widget );
$("<div class='widget_sub_header widget_sub_header_" + widget_shell.d[i].widget_id + "'>").appendTo( $widget );
$("<div class='widget_content widget_content_" + widget_shell.d[i].widget_id + "'>").appendTo( $widget );
$("<div class='widget_footer widget_footer_" + widget_shell.d[i].widget_id + "'>").appendTo( $widget );
}
each .widget will need controls such as buttons, textboxes etc in the .widget_sub_header section. What is recommended way of doing that? "That" as in, how to get further HTML controls into the .widget_sub_header. Add the HTML for the controls in the database? Somehow connect to an external file containing the HTML controls and add them in? or some other method?
I guess my 2 main concerns are:
Easy maintenance
Server resource friendly
jquery-ZenCoding is easy way to create some nested html elements :
https://github.com/zodoz/jquery-ZenCoding
exemple :
$.zen("div#widget>ul.instrument>(li{piano}+li{guitare}+li{flute})");
What about something like this? I suggest instead of adding a class with the id, add an actual id on the parent, that's all you need to target children elements.
function createWidget( id ) {
var widget = [
'<div class="widget">',
'<div class="widget_header"></div>',
'<div class="widget_sub_header"></div>',
'<div class="widget_content"></div>',
'<div class="widget_footer"></div>',
'</div>'
].join('');
return $( widget ).attr( 'id', 'widget_'+ id );
}
$.each( widget_shell.d, function( i,v ) {
$('.column_'+ v.column_id)
.append( createWidget( v.widget_id ) );
});
I'd add a small template engine. There is a very simple one made by John Resig that I use frequently at:
John Resig micro-templating
Chances are you'll be doing this sort off thing again so a template engine is pretty handy to have lying around.
If you don't like that one you can have a look at a great resource of micro-templates at:
Microjs templates
I've used to work on a similar widget system.
This is how I've managed it :
Have a hidden div container that holds all the template elements.
<div id='widget-templates'>
<div class='widget1-id' >
<input type='text' class='ytSearch'/>
<button id='btnYtSearch'>Search</button>
</div>
<div class='widget2-id'></div>
...
<!-- etc etc -->
...
</div>
I used an object called widgetFactory which holds all the javascript code needed to create a widget from the template.
var widgetFactory = {
youtubeSearch: function(data){
var $generatedWidget = $('#widget-templates > .widget1-id').clone();
// prepopulate with some data if requested (usually when binding data to an already existing widget)
// ...
// attach events
// ...
return $generatedWidget;
}
}
Then with external javascript logic, I would save just the widget data (as JSON) and widget type into the database.
tbl_widgets(id, name, type)
tbl_user_widget(user_id, widget_id, data)
Note that this is just from my memory and there probably is a much more profound solution, but i hope it could shine any new idea on your user customizing widget system.

Customizing JavaScript Visualization Toolkit Spacetree Node

I saw many people recommend JavaScript Visualization Toolkit (The JIT) for org chart. I am trying to use SpaceTree of JavaScript InfoVis Toolkit for org chart. The nodes in my org chart is like a component in itself that has employee profile pic, two different icons that show up overlays on click and some 3 lines of simple text having name, title, and number of reports ... each line is separated by a light horizontal line. Something like:
My question is, is it possible to customize the spacetree nodes to such an extent? Can I have Node almost like another "component" or JavaScript object that has its own render method?
I researched on forums and some options I considered are:
$jit.ST.NodeTypes.implement() ... but based on examples I saw, this
seem to be helping in customizing node in terms of shapes etc but
not like layout drawn above. I am referring to customization
something like:
http://groups.google.com/group/javascript-information-visualization-toolkit/browse_thread/thread/a4a059cbeb10ba23/ebf472366cdbbdef?lnk=gst&q=spacetree+nodetype#ebf472366cdbbdef
I tried to set innerHtml in onCreateLabel method in example5.js at:
but it seems to be doing nothing. Although, I'm not sure if that
will be a good way of node customization. Example5 is at the JIT website (I am not allowed to post more than one hyperlink)
Extending Graph.Node ... I am still looking into this option and it
this point of time, I don't know how complicated it is to have space
tree use Graph.myNode and what will Graph.myNode even look like? I
need to think more on those lines and see if it is even feasible.
The Spacetree can be customized very much. The nodes can display images or anything we want. We can have custom click events for the nodes. To have custom events, you will have to redraw the whole tree in the onclick event.
Here is an example. On the success function of the click event. Here I have called the click event on the class "clickable"
$.ajaxSetup({ cache: false });
$(".clickable").live("click", function () {
$.ajax({
url: url + "?id=" + parentId + "&ts=" + new Date().getMilliseconds(),
type: "POST",
cache: false,
dataType: "html",
success: function (html) {
init(html);
}
});
});
The name property can be used to give the image like this:
{id:"90", name:"<a href='javascript:;' class='clickable' name='90'><img src='images/picture.gif' width='30' height='30' alt='pic' /></a>", data:{}, children:[]}
Mark as Answer if useful. thanks.
You could make yourNode the prototype ancestor of Graph.node, set up the slots you want, then add the appropriate render / force code customizations.
I'm using spacetrees and I just set the label type to HTML (which is the default) and you can just use regular HTML and CSS to style your labels. I have images, links, text, etc.
Note that you're working with the label and not the node. The node is the graph component; the label is the visual that you see which represents the node.
When you initialize the spacetree pass in a function for "onCreateLabel":
var myOnCreateLabel = function(label, node) {
label.onclick = function(event) {/* setup onclick handler */};
label.innerHTML = "<img src='myImage.png' />"; // use image in label
};
var myST = new $jit.ST({/*other settings*/ onCreateLabel: myOnCreateLabel});
if you don't mind working with HTML5/Canvas only, try this as well http://orgplot.codeplex.com, simple interface support image node as well.
this.st=new $jit.ST(
{
onCreateLabel: function (label, node)
{
var labelContent = $('<table cellpadding="0" cellspacing="0" class="nodeContainer"><tr><td>' +
'<div class="buttonContainer">' +
'</div></td></tr><tr><td>' +
'<table class="nodeBox" cellpadding="0" cellspacing="0">' +
'<tr>' +
'<td class="iconTd"></td>' +
'<td class="center nodeName">' + node.name + '</td>' +
'</tr></table>' +
'</td></tr></table>');
thisObject.onCreateLabel.raise(thisObject, { labelContent: labelContent, node: node });
if (node.data && node.data.Icon && node.data.Icon != "")
{
labelContent.find(".iconTd").append($("<img src='" + node.data.Icon + "' alt=''>"));
}
else
{
labelContent.find(".iconTd").remove();
}
var lblCtl = $(label).append(labelContent);
if (node.data.Data.ChildrenCount)
{
labelContent.append("<tr><td class='subnode'></td></tr>");
}
if (node.name.length > 40)
{
lblCtl.attr("title", node.name);
node.name = node.name.substr(0, 37);
node.name = node.name + "...";
}
lblCtl.click(function (sender)
{
//thisObject.isNodeClicked = true;
var target = $(sender.target);
if (!target.hasClass("subnode"))
{
if (thisObject.currentSelectedNode)
{
thisObject.currentSelectedNode.buttonContainer.hide();
}
var btnContainer = labelContent.find(".buttonContainer");
thisObject.currentSelectedNode = { nodeElement: lblCtl, node: node, buttonContainer: btnContainer, event: sender };
btnContainer.append(thisObject.$globalButtonContainer.show()).show();
var button = target.closest(".chartActionButton");
if (button.length > 0)
{
thisObject.onNodeAction.raise(thisObject, { name: button.attr("name"), nodeElement: lblCtl, node: node, button: target });
}
else
{
thisObject.onNodeClick.raise(thisObject, thisObject.currentSelectedNode);
}
}
else
{
thisObject.st.onClick(node.id);
}
});
label.id = node.id;
//set label styles
thisObject.setNodeStyle(node.data.Style, label.style);
}
});

Categories

Resources