I have 2 menus, category and countries. I've made so far to change and keep background of one element but I have problem with simultaneous memory of other menu's element.
var lookaround=[];
function seleItem(obj,color){
if(lookaround[obj.className])
lookaround[obj.className].style.background=null;
lookaround[obj.className]=obj;
obj.style.background=color;
}
Example page is HERE
You should use an object instead of an array for lookaround:
var lookaround = {};
Related
so I'm making a product using fabric - trying to add sortable layers.. But with every jsfiddle example I find, I run into the SAME issue with every one..
The issue is: After you reorder the sortable layers, when you click on any given li it highlights the wrong canvas object.
You can recreate the issue if you go to the link below this paragraph, add a couple objects, then rearrange the li's then click on one of the li's that you moved around.. it will select the wrong object (let's say you add three layers, then move the first layer you added to the top, then click the top li it will not select the proper layer but rather I think the layer that was originally there?)
https://jsfiddle.net/peLcju2h/24/
I think the problem might be that the objectArray array isn't updating along when rearranging the layers - so when selecting one it selects from the original order that they were in?
At this area in the code:
`
$("#containerLayers").sortable({
update: function(event, ui){
var items = $(this).children();
items.each(function(i,item){
canvas.sendToBack(objectArray[item.id]);
});
canvas.renderAll();
}
});
$("#containerLayers").disableSelection();
`
I tried to put the object array code back in the sortable code area to repopulate the array every time the li's are reordered but this didn't work for me.. I tried something like this:
`
var objectArray = new Array();
var i='0';
var objects = canvas.getObjects();
objects.forEach(object=>{
var thisobject = objects[i];
i++;
});
objectArray.push(thisobject);
`
Any help would be GREATLY appreciated!!! :)
I'm trying to find a way to get the ids from dragged divs after they are in the drop zone.
All the drag components have an id from drag1 - drag8 and the drop zone is div drop zone. Because there are no divs in the drop zone when the page loads I want to gather the ids on a save button for now with a text box entry and drop down menu select.
I have tried the code below:
$(document).ready(function() {
$("#dropzone div").click(function() {
var index = $("#dropzone div").index(this);
$("#dropzone_drag").html("Index " + drag + " was clicked");
});
});
And I use jQuery for the text box, which works nicely:
$(document).ready(function() {
$('#save').click(function() {
alert($('#name').val());
});
});
How do I find the ids from dragged divs after they are in the drop zone?
After playing around i came up with the following:
var ids = {};
$("#dropzone>div").each(function(i){
ids[i] = $(this).prop('id');
});
which at the moment says undefined, but i did manage to put it on the save button so it no longer pops up when i open the page.
Any suggests please?
In my comprehension .index(this) returns the index of the element relative to the list "#dropzone div"., which may or may not contain the elements in the order you want. But if all your elements have a common class, say ".foo_bar" it probably would be easier to know the id given an clicked element.
Otherwise, as you're using this on the function, if this is one of your "drags" it is probably easier to pick the id from this than to try the indexes.
Try doing it like that and maybe it'll word better.
ids = {};
$("#dropzone>div").each(function(){
ids[$(this).prop('id')] = $(this).prop('id').replace(/[^0-9]/g, '');
});
the code .replace() means that we are removing characters (in this case anything that isn't a number) from the string so we end up with it's true number. Instead of it's place in the DOM.
If i didn't comprehend well your problem, correct my comprehension errors and i will edit the answer. And an html of the zones would be nice ;)
The following code worked for me:
<script>
var div = document.getElementById('dropzone')
</script>
and on the button i added:
alert( div.innerHTML )
The result gave me all of the div information from it's html page so i could select the information i wanted to push to the database.
Thank you all for you input and advice.
Matthew
I have a menu whose contents need to change significantly based on user interaction. This means that some new menu items need to be introduced, and some need to be removed. Looking at Dojo's published API documentation, there doesn't seem to be a way to redo a menu's contents without removing existing items and recreating the menu from scratch.
dijit/Menu's getChildren() method returns an array suggesting that there might be a relatively simple way of inserting menu options at specific index positions. Unfortunately, however, I can't find a way to attach an array of menu items into a dijit/Menu.
Does anyone know of a direct way (using the API)?
dijit/Menu is missing some fairly mainline use-cases. I made a custom implementation that added the various features I always seemed to want. Among them is toggling a given menu item.
I've pastebin'd my "dijit/ContextMenu" widget (my name, not theirs) here, but the answer is no, you have to do it yourself. You can either dynamically add/remove MenuItems as needed, or what I do is inject them all at creation-time, then show/hide as needed:
[snip]
hideMenuItem :function(menuItemId){
var menuItems = this.getChildren();
for(var i=0; i < menuItems.length; ++i){
if(menuItemId === menuItems[i].id){
domStyle.set(menuItems[i].domNode, "display", "none");
break;
}
}
},
showMenuItem : function(menuItemId){
var menuItems = this.getChildren();
for(var i=0; i < menuItems.length; ++i){
if(menuItemId === menuItems[i].id){
domStyle.set(menuItems[i].domNode, "display", "");
break;
}
}
}
[/snip]
The answer suggested by #gabriel was my starting point, and I noticed that it's possible to add menu items at a specific position by specifying the index in Menu.addChild.
addChild(widget,insertIndex)
What I ended up doing eventually was something different:
Loop through menu.getChildren() to the index that I was looking for
Remove the menu item (using removeChild)
Add new menu item (using addChild)
I couldn't use insertIndex since my menu had separators that needed to be handled (sigh!).
I have used firebug and IE profilers and can see what function in my code is causing the slowness. Being new to jquery, the recommendations that I have read online are not clear to me. I have made an example page that shows the slow behavior when you check or uncheck a check box. No surprise that this is fast using Chrome.
The function that is slow can be found on line 139.
$('.filters input').click( function()
JSFiddle can be found here
The code is 122 KB and can be found here
UPDATE: if you know of any examples online that are similar in function and faster, please share.
i had a brief look through your code, but it was very hard to follow. it seemed as if you were looping through things many many times. i used a much simpler approach to get the list of all states.
your approach was
* make a massive string which contained every class (possibly repeated multiple times)
* chop it up into an array
* loop through the array and remove duplicates
i simply took advantage of the fact that when you select something in jQuery you get a set rather than a single item. you can therefore apply changes to groups of object
$(document).ready(function () {
//this will hold all our states
var allStates = [];
//cache filterable items for future use
var $itemsToFilter = $(".filterThis");
//loop through all items. children() is fast because it searches ONLY immediate children
$itemsToFilter.children("li").each(function() {
//use plain ol' JS, no need for jQuery to get attribute
var cssClass = this.getAttribute("class");
//if we haven't already added the class
//then add to the array
if(!allStates[cssClass]) {
allStates[cssClass] = true;
}
});
//create the container for our filter
$('<ul class="filters"><\/ul>').insertBefore('.filterThis');
//cache the filter container for use in the loop
//otherwise we have to select it every time!
var $filters = $(".filters");
// then build the filter checkboxes based on all the class names
for(var key in allStates) {
//make sure it's a key we added
if(allStates.hasOwnProperty(key)) {
//add our filter
$filters.append('<li><input class="dynamicFilterInput" type="checkbox" checked="checked" value="'+key+'" id="filterID'+key+'" /><label for="filterID'+key+'">'+key+'<\/label><\/li>');
}
}
// now lets give those filters something to do
$filters.find('input').click( function() {
//cache the current checkbox
var $this = $(this);
//select our items to filter
var $targets = $itemsToFilter.children("li." + $this.val());
//if the filter is checked, show them all items, otherwise hide
$this.is(":checked") ? $targets.show() : $targets.hide();
});
});
FIDDLE: http://jsfiddle.net/bSr2X/6/
hope that's helpful :)
i noticed it ran quite a bit slower if you tried to slideup all the targets, this is because so many items are being animated at once. you may as well just hide them, since people will only see the ones at the top of the list slide in and out of view, so it's a waste of processor time :)
EDIT: i didn't add logic for show all, but that should be quite a trivial addition for you to make if you follow how i've done it above
You could use context with your selector:
$('.filters input', '#filters_container').click(function()...
this limits the element that jQuery has to look in when selecting elements. Instead of looking at every element in the page, it only looks inside your $('#filters_container') element.
I need a tree menu. But instead of a listview where you expand/collapse i need a dropdown box with the list and when you click on a element i need the box to update (with the first entry being 'Back') so the menu stays in a neat little dialog.
Does this menu have a name? Does anyone know where i can get code to do this?
I can think of several jQuery plugins which would soot your purposes. However, I would recommend jQuery iPod Style Drilldown Menu (Newer Version), which is exactly what it sounds like. The dropdown box updates in place, uses a cool sideways slide animation, and includes a "Back" button (as you desired). Finally, if you don't want any animation, you can try tweaking the plugin's many options. Setting crossSpeed to 0 may work, for example.
Adam is right, jQuery offers an assortment of menu's which you could use. Really though, this is a somewhat trivial problem, the code to write it would take up about 1/10th the space that jQuery's code will. So if possible I would say write it without jQuery.
The most effective method would be to do it JS OOP (Javascript Object-Oriented), but understandably this is a confusing topic.
Basically you just want something like:
function drillDown(){
//Any code that multiple drilldowns
// might need on the same page goes here
//Every instance of a drillDown will
// instantiate a new set of all functions/variables
// which are contained here
//A reference to the parent node the dropdown is placed in
this.parent;
//A reference to the div the dropdown is incased in
this.object;
//Returns a reference to this object so it can be
// stored/referenced from a variable in it's
// superclass
return this;
}
//Prototype Functions
//prototypes are shared by all
// instances so as to not double up code
//this function will build the dropdown
drillDown.prototype.build = function(parent){
//Too lazy to write all this, but build a div and your select box
// Add the select box to the div,
// Add the div to the parent (which is in your document somewhere)
var divEle = document.createElement('div');
var inputBox = document.createElement('input');
//code code code
divEle.appendChild(inputBox);
parent.appendChild(divEle);
}
//this function loads the newest dataset of
drillDown.prototype.loadNewDataSet = function(data){
//first clear out the old list
// remember we have a reference to both the
// 'object' and 'parent' by using
// this.object and this.parent
//load the data, we are going to use the text from
// the select boxes to load each new dataset, woo eval();
// If you didn't know, eval() turns a string into JS code,
// in this case referencing an array somewhere
var dataSet = eval(data);
//then loop through your list adding each new item
for(item in dataSet){
//add item to the list
//change the .onClick() of each one to load the next data set
// a la ->
selectItem.onClick = function(){this.loadNewDataSet(item);};
//if you name your datasets intelligently,
// say a bunch of arrays named for their respective selectors,
// this is mad easy
}
}
//Then you can just build it
var drillDownBox = new drillDown();
drillDownBox.build(document.getElementsByTagName('body')[0]);
drillDownBox.loadNewDataSet("start");
//assuming your first dataset array is named "start",
// it should just go
And by the way, Adam also said it, but wasn't explicit, this is refered to as a drill-down.