I am using dragula.js, and using ondrop event in mycode,
drake.on('drop', function (el) {
console.log(el); //result <div>foo bar</div>
var n = typeof(el); //return object
var x = el.indexOf("test"); //error TypeError: el.indexOf is not a function(…)
// do another code
})
I want to check if "test" exist on el parameter, but error occur. thx.
I think it should be as easy as if ('test' in el)
Use the dom. Roughly: el.parentElement.children.indexOf(el)
Solved - https://github.com/bevacqua/dragula/issues/209
indexOf works on strings, so you need to call it using the element's text, rather than the element itself, like so:
el.textContent.indexOf("test");
Edit:
Looks like you want the index of the dragged element rather than matching its text:
[].slice.call(el.parentElement.children).indexOf(el)
Related
I've been looking all over the web for how to do this. I am trying to make Jquerys .html() function in vanilla JavaScript. I want to recreate so I can understand it better. I've tried the following but nothing seems to work, I just don't understand what I am doing wrong.
let $ = function(ele) {
if (ele.charAt(0) == '.' || ele.charAt(0) == '#') {
let newEle = cut(ele,0);
if (ele.charAt(0) == '#')
get(newEle);
else
return document.getElementsByClassName(newEle);
} else
return document.getElementById(ele);
}
$.prototype.html = function(html) {
this.innerHTML = html;
}
$('test').html('hey');
$('.hey')[0].html('hey');
function cut(string,num) {
let a = string.slice(0,num);
let b = string.slice(num + 1,string.length);
return a + b;
}
It doesn't work, the console log reports this error:
Uncaught TypeError: $(...).html is not a function
Please help and thanks in advance.
The problem here is what you are returning from the $ function.
Think about this: document.getElementsByClassName and document.getElementById return dom elements and dom elements don't have a .html function. That is why you are getting the error.
What you need is to return is an object, a wrapper, with a .html function, and a closure over the dom elements that you want to modify.
Because you're returning an object from $, you're overriding the default behavior of new $; instead of resulting in the newly-created object, it results in the object you returned out of $.
Instead, you'd want to remember the results of those getElementsByClassName/getElementById calls in an array or Set you store on this (the newly-created object), and then use that array or Set within html (since you want to loop over all matching elements in the case where you're setting the new HTML).
Side note: Since you're using ES2015+ features anyway (let), you might want to use the simpler class syntax instead of a separate function declaration and assigning to $.prototype:
class $ {
constructor(ele) {
// ...
}
html(html) {
// ..
}
}
I wanna make a varible shortcut $$() so that i can use shortcut like $() [jquery] to save code in my project(ALL MY CODE IS PURE JAVASCRIPT).
when i put the string of id or class, it works all right, but when i put the tagName, it shows Cannot read property 'style' of undefined, it seems that the code is right,help,thanks
One more, is that way to defined a shortcut variable $$() to use in pure javascript environment right way? or is there any best practice to define a global variable like this?
window.onload = function(){
function $$(ele){
var pattern1 = /#/g;
var pattern2 = /\./g;
var pattern3 = /!/g;
var matches = ele.match(/[^#\.!]/g);//array
var elementS = matches.join("");
//alert(matches+elementS);
// console.log(document.getElementsByTagName(elementS));
var spaceExist = /\s/.test(elementS)
if(pattern1.test(ele)){
return document.getElementById(elementS);
}else if(pattern2.test(ele)){
//console.log(elementS);
return document.getElementsByClassName(elementS);
}else if(pattern3.test(ele)){
alert('hi');
console.log(elementS);
return document.getElementsByTagName(elementS);
}else if(spaceExist){
return document.querySelectorAll(elementS);
}
}
$$('#hme').style.backgroundColor = 'red';
$$('.myp')[0].style.backgroundColor = 'green';
$$('!h2')[0].style.display = 'none';//this not work,shows Cannot read property 'setAttribute' of undefined
}
<h1 id="hme">hi,friend</h1>
<p class="myp">mmdfdfd</p>
<h2>hhhhhh</h2>
Have you stepped through your code? Look at pattern #2:
var pattern2 = /./g;
That pattern will match any character at all given that's what the period represents in regular expressions - ref: http://www.regular-expressions.info/dot.html.
Therefore, this conditional is satisfied and returns its result:
else if(pattern2.test(ele)){
return document.getElementsByClassName(elementS);
}
Given there appears to be no element with a class name of h2 (which is the value of elementS), the return value is undefined.
Given that undefined has no properties, interrogating for the style property will produce the error you are seeing.
My advise is use one shortcut since you already using querySelectorAll:
window.$ = document.querySelectorAll.bind(document)
or if you rather need first element
window.$ = document.querySelector.bind(document)
this way you'll be able to do everything you are doing with normal css selectors and not obfuscated !tag for just tag
If speed actually matters, you will save some ticks by just having two aliases:
window.$ = document.querySelector.bind(document)
window.$el = document.getElementById.bind(document)
and calling $el when you need it specifically, instead of trying to make method polymorph.
Mister Epic's answer spots the main issue. Your h2 call is getting caught in that if statement, and that's why your error is happening. You need to make sure it doesn't get caught there, either by creating another pattern, or specifying in your second if statement that your 'ele' doesn't contain an '!'.
After that, in your third if statement:
else if(pattern3.test(ele)){
alert(hi); <---
console.log(elementS);
return document.getElementsByTagName(elementS);
The problem with this is you're going to alert(hi), but hi isn't defined. Make sure you wrap it in quotes.
Should be looking good after that.
What is the problem with this code?
var lines = document.getElementById('id="summoners"').val().split('\n');
//I get error above "Cannot call method val of null
for(var i = 0;i < lines.length;i++)
{
//other code using lines[i] not necessary to show it
}
document.getElementById('summoners') is the syntax you'd want to access the element and is why you're getting the null reference exception.
.val() is a jQuery-like method, though, and will fail on a raw HTML element. You'd need to use something like document.getElementById('summoners').value, assuming it's a textarea element, or use jQuery and do $('#summoners').val().
Your getElementById is malformed. You need not specify the "id" key in the method argument. Go with:
document.getElementById('summoners').val().split('\n');
I'm using custom tags to define sections in an application, so I have something like this:
<mysection>
<form>
<input name="myfield">
</form>
</mysection>
I'm using the following and able to get the tag (printed to console, everything is groovy)
var parent = document.getElementsByTagName('mysection');
The issue I'm having is finding the child field by name:
var myfield = parent.getElementsByName("myfield");
...as I don't want to pick up on any other 'sections' that might have an input with the name 'myfield'.
EDIT:
var parent = document.getElementsByTagName('mysection')[0];
was suggested and returns to console the section contents, however, getElementsByName throws an error:
Uncaught TypeError: Object #<NodeList> has no method 'getElementsByName'
Using getElementsByTagName() and getElementsByName() will return a NodeList, you need to get the first element of the list like this:
var parent = document.getElementsByTagName('mysection')[0];
var myfield = parent.getElementsByName("myfield")[0];
Edit
You were correct, getElementsByName is not valid for an element. I am unsure how to localize the functionality of it as you are trying to do. It seems that it will only work for document. You may have to write your own implementation of getElementsByName if you want to use it in a localized scope.
Second Edit
To be nice, I made that implementation for you :D Here it is in all its "glory".
Element.prototype.getElementsByName = function (arg) {
var returnList = [];
(function BuildReturn(startPoint) {
for (var child in startPoint) {
if (startPoint[child].nodeType != 1) continue; //not an element
if (startPoint[child].getAttribute("name") == arg) returnList.push(startPoint[child]);
if (startPoint[child].childNodes.length > 0) {
BuildReturn(startPoint[child].childNodes);
}
}
})(this.childNodes);
return returnList;
};
var parent = document.getElementsByTagName('mysection')[0];
var myfield = parent.getElementsByName("myfield")[0];
Small fix
I was incorrectly passing the element and not its children into the recursion. The code above has been edited with the proper argument passed now. See working fiddle: http://jsfiddle.net/js6NP/5/
I actually found a much more simple way to handle this:
document.querySelectorAll('mysection [name="myfield"]');
Here you can see an example where it only modifies the field inside the section specified: http://jsfiddle.net/fluidbyte/kph6H/
qSA supports modern browsers and is compatible down to IE8, Here's a polyfill to support back to IE7: https://gist.github.com/2724353
getElementsByName won't work on a DOM element reference. Use querySelector or querySelectorAll instead. In example:
var parent = document.getElementsByTagName('mysection')[0];
var myfield = parent.querySelector("[name='myfield']");
Just use an ID instead:
<mysection>
<form>
<input name="myfield" id="fieldName">
</form>
</mysection>
var myfield = document.getElementById("fieldName");
ID's are supposed to be unique on a page. So you shouldn't have trouble accessing the right element.
If you really have to use name/tagname, getElementsByTagName and getElementsByName both always return a array (A empty one if no element was found). you can access the right element, just like you'd access elements in arrays:
document.getElementsByTagName('mysection')[0]; For the first element with tagname mysection.
If I do this:
$('.classname').html(Math.floor(Math.random()*10)+1);
All of "classname" is filled with the same number.
Is it possible to fill every instance of "classname" with a different random number?
The only possible way I can think of solving this is to go through each instance of "class name" and apply a random number one by one.
.html()
$(".classname").html(function(idx, oldValue) {
return (Math.floor(Math.random()*10)+1);
});
fiddle
the html method has an "overload" that accepts a function. The function should return the value to set the inner html to. In your case you can do:
$(".classname").html(function() {
return (Math.floor(Math.random()*10)+1);
});
the function is actually called with two arguments. The first is the index of the element in the selection and the second is the current value of the elements inner html
You can use jQuery's .each() function to iterate over each element matching the selector you provide -
$.each('.classname',function(index,elem){
var newRandomNumber = (Math.random()*10)+1;
$(elem).html(Math.floor(newRandomNumber));
});
For every iteration of the each() function, you'll have the index of the element you are on and the element itself in the elem parameters.
http://api.jquery.com/jQuery.each/
try this
$('.classname').each(function(index) {
$(this).html(Math.floor(Math.random()*10)+1);
});
Yes. The easiest way to do so would be using the jQuery each function:
$('.classname').each(function() {
$(this).html(Math.floor(Math.random()*10)+1);
});