Sorry for this absolute noob question.
I am trying to implement Tabs with this MooTools Plugin:
http://mootools.net/forge/p/simple_tab_pane
The syntax for the constructor is as follows:
var myTabPane = new TabPane('tabs', {
tabSelector: 'li',
contentSelector: 'p'
});
Where 'tabs' is the CSS-id of the container.
Now I would prefer to use a class for the container but '.tabs' won't work.
What would be the correct syntax for this?
And how should i do it to adress for example every div-Element ?
well first things first - what is expected:
https://github.com/akaIDIOT/MooTools-TabPane/blob/master/Source/TabPane.js#L44
he expects argument to be an element id or an actual element. how you arrive to that element is up to you.
var myTabPane = new TabPane(document.getElement('.tabs'), {
tabSelector: 'li',
contentSelector: 'p'
});
passing an element found based upon a class search for .tabs.
alternatively, you can re-implement the initialize method on the class and write the line as:
this.container = document.getElement(container);
this.container.getElements(this.options.contentSelector).setStyle('display', 'none');
so you can then pass a jquery like selector: new TabPane('#someid') or new TabPane('div.someclass')
You'd refactor it by doing TabPane.implement({ initialize: fn(){... }) or do a subclass like var myTabs = new Class({extends: TabPane, initialize: fn(){ ... }). When you extend, this.parent() will call the parent method over the prototype.
Related
I am using the code-mirror component from the Polymer Designer, and can set the initial value, but cannot see how to get changes to the code from the user.
I initialise the code-mirror using
<code-mirror id="code_mirror" value="{{code}}">
</code-mirror>
and would like to listen for changes in {{code}}, but codeChanged doesn't seem to fire.
I know I can get the actual value using code_mirror.$.mirror.getValue(), but would like to use data-binding.
I have tried using on-change to no avail.
Assuming you're using https://github.com/PolymerLabs/code-mirror what you need to do is make the CodeMirror instance created in the ready handle some events that the instance itself is emitting, then make the code-mirror element fire any custom event (something which I know is called event relay)
The following example makes the polymer element fire the custom event code-change whenever the editor value is changed
ready: function() {
var me = this;
//...
this.mirror = CodeMirror(this.shadowRoot, { /* ... */ });
this.mirror.on('change', function () {
// me = polymer instance
me.fire('code-change', { value: me.mirror.getValue() })
});
}
Then any instance of the polymer custom element would need to listen to that event using Polymer's declarative event mapping or through addEventListener
1st case (if code-mirror is inside another <polymer-element />):
<code-mirror on-code-change="{{ onCodeChange }}"></code-mirror>
// ...
<script>
Polymer({
onCodeChange: function(event, detail, sender) { ... }
});
</script>
2nd case ():
<code-mirror></code-mirror>
<script>
document
.querySelector('code-mirror')
.addEventListener('code-change', function () { ... });
</script>
I have 5 a elements that I need to inject with additional span , instead of creating new Element 5 times how can I do this only once ? I tried
var holders= $$('.holders');
holders.each(function (el){
var addspan = new Element('span', {
'class': 'over'
});
el.inject(addspan , 'top');
});
but it does not work
any help is appreciated , thank you!
Injection works the other way around; it injects an element into another one. Try reversing addspan and el.
Another option would be to use the adopt function, which might be more intuitively meant to have an element adopt another one.
Like akaIDIOT already mentioned, you have to swap addspan and el when using the inject method. To save a line of code, you can chain the inject method with the new element like this:
var holders= $$('.holders');
holders.each(function(el) {
var addspan = new Element('span', {
'class': 'over'
}).inject(el, 'top');
});
How can I bind an observable to an editable div text content?
You will need to modify the default "text" binding so that it is able to write the content of the edited div back to the observable. A simple custom binding handler for this task can look like this:
ko.bindingHandlers.editableText = {
init: function(element, valueAccessor) {
$(element).on('blur', function() {
var observable = valueAccessor();
observable( $(this).text() );
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).text(value);
}
};
But please note that this example code requires jQuery.
Usage is as simple as this:
<div contentEditable="true" data-bind="editableText: foo"></div>
Here is an example (written in CoffeeScript): http://jsfiddle.net/aBUEu/1/
You can't do that by default, because changing text in editable div won't raise any event that would update the value in your model.
You will need a custom binding for this. You can read about it here: http://knockoutjs.com/documentation/custom-bindings.html
I am using Jquery 1.7.2.
I want to transverse Html Elements Till a Specifc Attribute (id) using Jquery on
mouse over on any html element in my page.
we have parents() function but problem is how to select stop on the parent element which has id attribute
$("*", document.body).click(function (e) {
e.stopPropagation();
var domEl = $(this).get(0);
var parentEls = $(domEl).parents()
.map(function () {
return this.tagName;
})
.get().join(", ");
$("b").append("" + parentEls + "");
});
this is code but i am getting all element till root
but i want to stop on a closet elements which has attribute id in the tag
Please help me out .
Just use closest:
$(this).closest('#the-id');
Unless your'e just looking for the closest one that has any id attribute, which would be:
$(this).closest('[id]');
Edit: after seeing your updated question, this should be what you want:
$(document).click(function(e) {
e.preventDefault();
var parents = $(e.target).parentsUntil('[id]')
.map(function() { return this.tagName; }).get().join(',');
console.log(parents);
});
Note that this approach accomplishes what you want without selecting and binding click events to every node in the DOM, which is a pretty heavy handed approach.
Edit (again): looks like maybe you wanted to include the tag with the id attribute on it (the above solution is everything up to, but not including that tag). To do this, the solution is pretty similar:
$(document).click(function(e) {
e.preventDefault();
var $parents = $(e.target).parentsUntil('[id]');
var tagNames = $parents.add($parents.parent())
.map(function() { return this.tagName; }).get().join(',');
console.log(tagNames);
});
It looks like you want to map the hierarchy from the clicked element up to the document root. In that case, you can apply parents() to event.target:
$(document).click(function(e) {
e.preventDefault();
var parentEls = $(e.target).parents().map(function() {
return this.tagName;
}).get().join(", ");
});
Note that, as jmar777, you should also change your selector: "*" adds an event handler to all the elements, which is probably not what you want. Bind a single handler to document instead to take advantage of event bubbling.
Say I have a DOM that looks like this in my Document:
<body>
<div id="outer">
<custom-web-component>
#shadow-root (open)
<div id="inner">Select Me</div>
</custom-web-component>
</div>
</body>
Is it possible to select the inner div inside the shadow root using a single querySelector argument on document? If so, how is it constructed?
For example, something like document.querySelector('custom-web-component > #inner')
You can do it like this:
document.querySelector("custom-web-component").shadowRoot.querySelector("#inner")
In short, not quite. The TL:DR is that, depending on how the component is set up, you might be able to do something like this:
document.querySelector('custom-web-component').div.innerHTML = 'Hello world!';
Do do this - if you have access to where the web component is created, you can add an interface there to access inner content. You can do this the same way you would make any JavaScript class variable/method public. Something like:
/**
* Example web component
*/
class MyComponent extends HTMLElement {
constructor() {
super();
// Create shadow DOM
this._shadowRoot = this.attachShadow({mode: 'open'});
// Create mock div - this will be directly accessible from outside the component
this.div = document.createElement('div');
// And this span will not
let span = document.createElement('span');
// Append div and span to shadowRoot
this._shadowRoot.appendChild(span);
this._shadowRoot.appendChild(this.div);
}
}
// Register component
window.customElements.define('custom-web-component', MyComponent);
// You can now access the component 'div' from outside of a web component, like so:
(function() {
let component = document.querySelector('custom-web-component');
// Edit div
component.div.innerHTML = 'EDITED';
// Edit span
component._shadowRoot.querySelector('span').innerHTML = 'EDITED 2';
})();
<custom-web-component></custom-web-component>
In this instance, you can access the div from outside of the component, but the span is not accessible.
To add: As web components are encapsulated, I don't think you can otherwise select internal parts of the component - you have to explicitly set a way of selecting them using this, as above.
EDIT:
Saying that, if you know what the shadow root key is, you can do this: component._shadowRoot.querySelector() (added to demo above). But then that is quite a weird thing to do, as it sorta goes against the idea of encapsulation.
EDIT 2
The above method will only work is the shadow root is set using the this keyword. If the shadow root is set as let shadowRoot = this.attachShadow({mode: 'open'}) then I don't think you will be able to search for the span - may be wrong there though.
This code will behave like query selector and work on nested shadowDoms:
const querySelectorAll = (node,selector) => {
const nodes = [...node.querySelectorAll(selector)],
nodeIterator = document.createNodeIterator(node, Node.ELEMENT_NODE);
let currentNode;
while (currentNode = nodeIterator.nextNode()) {
if(currentNode.shadowRoot) {
nodes.push(...querySelectorAll(currentNode.shadowRoot,selector));
}
}
return nodes;
}