I use a lot of the following expressions in my code:
document.
.getElementsBy...
.querySelector...
I need to save characters without using any libraries. That can be done by
var d = document;
Then, instead of document. I can write d. now.
I am wondering if there is a simple way to do the same thing for methods
.getElementsBy... and .querySelector....
Since these have a variable term, I cannot put the entire thing into a
variable, like var q = .querySelector(".class"), because the .class
changes almost every time.
You can create functions to avoid adding properties to the document object as shortcut if you don't want to.
function gEBI(d,id)
{
return d.getElementById(id);
}
function qS(d,s)
{
return d.querySelector(s);
}
var d = document;
var ele1 = gEBI(d,"yourID");
var ele2 = qS(d,".class");
You can make your own shortcut functions-references manually.
document.gEBI = document.getElementById;
document.gEBI(id);
But it's not a good practice to make such shortcuts.
Related
I'm fairly new to javascript so please go easy on me,
I have this code on a webpage:
<script type="text/javascript"> bb1 = "oldcode"; bb2 = "morecodehgere"; bb3 = 160000;</script>
I want to replace 1% of all page loads oldcode to newcode
There are multiple instances of this code on the same page and I want to replace them all.
window.onload = replaceScript;
function replaceScript() {
var randomNumber = Math.floor(Math.random()*101);
var toReplace = 'oldcode';
var replaceWith ='newcode';
if randomNumber == 1 {
document.body.innerHTML = document.body.innerHTML.replace(/toReplace/g, replaceWith);
}
}
This is the current code I've got but it doesn't work.
Is javascript the bast way to achieve what I'm looking to do? If so whats the best way to do this?
The regular expression literal:
/toReplace/g
will create a regular expression object that matches the string "toReplace". If you want to create a regular expression to match the (string) value of the variable toReplace, you must use the RegExp constructor:
var re = new RegExp(toReplace, 'g');
It is not a good idea to replace the innerHTML of the body with a copy of itself. The innerHTML property doesn't necessarily reflect all the nuances of the DOM and will not include things like dynamically added listeners. It also varies from browser to browser.
Using a regular expression to replace parts of innerHTML is almost certain to produce unpredictable results, it may work well on trivial pages but will not be reliable on complex pages.
I have an array of data. I have put this data on my site in different places over different attributes, how innerHTML value placeholder etc.
Is it possible to link this values with the array from where I can take data? So that when I change the data in array, it going automatic changed on the site?
Also I try to show how I did it mean:
var test = Array();
test['place1'] = 'NY';
var myspan = document.createElement('span');
myspan.innerHTML = test['place1'];
On some event the value of test['place1'] is changed to 'LA', and at the same moment the value of myspan.innerHTML must be changed too.
Native JS only please.
This needs to be manually managed. A simple solution would be something like this:
function Place(container, initVal) {
this.container = container ? container : {};
this.set(initVal);
}
Place.prototype.place = "";
Place.prototype.get = function() {
return this.place;
}
Place.prototype.set = function(val) {
this.place = val;
this.container.innerHTML = val;
}
var test = {}; // object
test['place1'] = new Place(document.createElement('span'), "NY")
test['place1'].set('New Value');
This is not a full-feature solution, but gives you an idea of the coordination that needs to take place.
If you're only supporting modern browsers, then the syntax can be cleaned up a bit by using getters/setters.
In the future, you'll be able to use Proxy, which will make it even easier and cleaner.
There is no native way to bind an attribute of an HTML element to the values of an array, but you aren't actually using an array; you're using an object, and it is a simple matter to define special features on an object. For example:
First, define your object:
function boundArray(){
this._bindings = {};
this.setBinding = function(key,element){
this._bindings[key] = element;
};
this.setValue = function(key,value){
this[key] = value;
if(this._bindings[key]){
this._bindings[key].innerHTML = value;
}
}
}
Then use it in your code:
// create a new instance of the boundArray
var test = new boundArray();
// create the HTML element to use, and add it to the DOM
var myspan = document.createElement('span');
document.body.appendChild(myspan);
// bind the HTML element to the required key in the boundArray
test.setBinding('place1',myspan);
// Now every time you set that key on the boundArray (using setValue), it will also change the innerHTML field on the element
test.setValue('place1','NY');
// You can access your information from the boundArray in the usual ways:
var somevar = test.place1;
var anothervar = test['place1'];
What you are talking about is an MVVM solution. Most MVVM JavaScript solutions uses some object that represents an observable, which is a field within the object. When the value in the object changes, the observable lets the framework know to update the DOM. It also listens to the DOM for change events, and updates the object in reverse. For arrays, it's a similar process: it listens for adds or removes of the array, and updates the UI accordingly.
As #MCL points out in the comments on this post below, there is a way to watch changes to an object, and it isn't overly difficult to generically attach to an element on the DOM. However, There are a lot of good frameworks out there that make this REALLY easy, so that may be something to consider.
I'm a beginner in JQuery,
How can I get the control as a javascript object from a JQuery object
var _object = $(this). ??
Most common
var _object = $(this)[0];
If you have more than 1 elements matched: $(this)[0], $(this)[1], $(this)[2] and so on.
$(this).get() is also possible. It's only advantage over the array model is that it allows selection of the kind $(this).get(-1) where it gets you the last matched object
var _object = $(this)[0];
I think this is right, can't check though because I'm on my phone.
In your case, simply use this.
$(this)[0] == this if this is a DOM element. If it's something else, e.g. a selector, $(this)[0] is the way to go.
(function (e) {
var a = false;
try {
$(this)[0];
a = true;
} catch (h) {}
alert(a.toString());
})(window);
I find myself often needing addClassName and removeClassName functions for Elements. However, I dare not to extend the native Element due to potential collisions. So, now I am wondering what to do.
I took a look at ExtJS, and it achieves this like:
var element = document.getElementById('...');
var elem = new Ext.Element(element);
elem.addClass('something');
I like the idea of not extending the native Element here, but I do not really like the idea of wrapping the element so hard over a custom object, because now I can't do several things like setAttribute easily, for example:
var element = document.getElementById('...');
var elem = new Ext.Element(element);
elem.addClass('something');
elem.setAttribute('src', '...'); // Fails
However, I could do:
var element = document.getElementById('...');
element.setAttribute('src', '...');
var elem = new Ext.Element(element);
elem.addClass('something');
but to me this does not look really nice. It looks a bit complex instead.
Are there any other alternative ways I could use besides wrapping the element around my own object that offers me these cool methods?
Just check if there's already an implementation defined. I'm pretty sure addClassName is not going to have a different signature than you have at the moment.
if (!node.prototype.addClassName) {
node.prototype.addClassName = function addClassName(name) {
// your code
}
}
Let's say I'm generating markup through server-side code. I'm generating a bunch of HTML tags but I want to add custom client-side behavior.
With JavaScript (if I had a reference to the DOM node) I could have written:
var myDOMNode = ...
myDOMNode.myCustomAttribute = "Hi!";
Now the issue here is that I don't want to qualify every element with an unique id just to initialize data. And it's really strange to me, that there's not an easier and unobtrusive way to attach client-side behavior.
If I'm remembing this correctly, this is valid IE stuff.
<div onload="this.myCustomAttribute='Hi!'"></div>
If I was able to do this, I should be able to access it's "data context" though the identifier 'myCustomAttribute', which is really what I want.
The following will work but not validate:
<div myattribute="myvalue"></div>
But if you are injecting it into the HTML with Javascript, then perhaps that's not concern for you. Otherwise, you can use something like jQuery to process the elements before adding them to the DOM:
$(elements).each(function(){
$(this).attr('myattribute','myvalue');
});
First off you should access custom attributes using the getAttribute and setAttribute methods if you want your code to work on other browsers than IE.
As to your event handler question that really depends on how you add the event handler.
Assigning a function directly to the elements onXXXX property would allow you access the the element via this.
If you use IE's attachEvent you can't use this, you can access the element that generated the event using event.srcElementbut that may be child element of the div. Hence you will need to test for the existance of myCustomAttribute and search up the ancestors until you find it.
I do appricate the input but I've finally figured this out and it's the way I go about initialization that has been the thorn in my side.
What you never wan't do is to pollute your global namespace with a bunch of short lived identifiers. Any time you put id="" on an element you're doing exactly that (same thing for any top level function). By relying on jQuery, HTML5 data and CSS there's a solution to my problem which I think is quite elegant.
What I do is that I reserve a CSS class for a specific behavior and then use HTML5 data to parameterize the behavior. When the document is ready, I query the document (using Query) for the CSS class that represents the behavior and initialize the client-side behavior.
I've been doing a lot of ASP.NET and within this context both the id="" and name="" belongs to ASP.NET and is pretty useless for anything else than internal ASP.NET stuff. What you typically find yourself doing is to get at a server-side property called ClientID you can refer to this from client-side JavaScript, it's a lot of hassle. They made it easier in 4.0 but fundamentally I think it's pretty much broken.
Using this hybrid of CSS, HTML5 data and jQuery solves this problem altogether. Here's an example of an attached behavior that uses regular expressions to validate the input of a textbox.
<input type="text" class="-input-regex" data-regex="^[a-z]+$" />
And here's the script:
$(function () {
function checkRegex(inp) {
if (inp.data("regex").test(inp.val()))
inp.data("good-value", inp.val());
else
inp.val(inp.data("good-value"));
}
$(".-input-regex")
.each(function () {
// starting with jQuery 1.5
// you can get at HTML5 data like this
var inp = $(this);
var pattern = inp.data("regex");
inp.data("regex", new RegExp(pattern));
checkRegex(inp);
})
.keyup(function (e) {
checkRegex($(this));
})
.change(function (e) {
checkRegex($(this));
})
.bind("paste", undefined, function (e) {
checkRegex($(this));
})
;
});
Totally clean, no funky id="" or obtrusive dependency.
In HTML5 there are HTML5 data attributes introduced exactly for the case.
<!DOCTYPE html>
<div data-my-custom-attribute='Hi!'></div>
is now corect, validating html. You can use any name starting with data- in any quantity.
There is jQuery .data method for interaction with them. Use .data( key ) to get, .data(key, value) to set data-key attribute. For example,
$('div').each(function () {
$(this).html($(this).data('myCustomAttribute')).data('processed', 'OK');
});
How about this?
<script>
function LoadElement(myDiv)
{
alert(this.myCustomAttribute);
}
</script>
<div onload="LoadElement(this)"></div>
not tested btw
Since you're trying to do this for multiple elements, you may try name attributes and getElementsByName.
<div name="handleonload">...</div>
window.onload = function () {
var divs = document.getElementsByName('handleonload');
for (var i = 0; i < divs.length; i += 1) {
divs[i].foo = 'bar';
}
};
Alternatively, you can use selectors, using libraries (such as jQuery and Prototype) and their respective iterators. This will also allow for you to search by other attributes (such as class).
Though, be cautious with your terminology:
obj.property = value;
<tag attribute="value">
<div style="width:100px;height:100px;border:solid black 1px" myCustomAttribute='Hi!' onclick="alert(myCustomAttribute);"></div>
The onload event is used for server side events. Its not part of the standard html element events.
Take a look at the following functions (especially the walk_the_dom one):
// walk_the_DOM visits every node of the tree in HTML source order, starting
// from some given node. It invokes a function,
// passing it each node in turn. walk_the_DOM calls
// itself to process each of the child nodes.
var walk_the_DOM = function walk(node, func) {
func(node);
node = node.firstChild;
while (node) {
walk(node, func);
node = node.nextSibling;
}
};
// getElementsByAttribute takes an attribute name string and an optional
// matching value. It calls walk_the_DOM, passing it a
// function that looks for an attribute name in the
// node. The matching nodes are accumulated in a
// results array.
var getElementsByAttribute = function (att, value) {
var results = [];
walk_the_DOM(document.body, function (node) {
var actual = node.nodeType === 1 && node.getAttribute(att);
if (typeof actual === 'string' &&
(actual === value || typeof value !== 'string')) {
results.push(node);
}
});
return results;
};
With the above two functions at hand, now we can do something like this:
some link
<script>
var els = getElementsByAttribute('dreas');
if (els.length > 0) {
els[0].innerHTML = 'changed text';
}
</script>
Notice how now I am making finding that particular element (which has an attribute called dreas) without using an id or a class name...or even a tag name
Looks like jQuery is the best bet for this one based on my searching. You can bind an object to a DOM node by:
var domNode = ...
var myObject = { ... }
$(domNode).data('mydata', mymyObj);
then you can call the data back up the same way, using your key.
var myObect = $(domNode).data('mydata');
I assume you could also store a reference to this within this object, but that may be more info then you really want. Hope I could help.