Extending every html element - javascript

With x-tag I am trying to find a way to extend every html element that I put is:"ajax-pop" attribute.
What I want to do is when I click an element with is:"ajax-pop" attribute I will do some dynamic ajax loads. It will be a good starting point for me to develop a manageble system.
I know I can do it with some different ways but I am wondering is there a way to do it like this way extends:'every single native html element'
xtag.register('ajax-pop', {
extends: 'WHAT SHOULD I WRITE HERE???',
lifecycle: {
created: function () {
},
inserted: function () {
},
removed: function () { },
attributeChanged: function () { }
},
methods: {
someMethod: function () { }
},
accessors: {
popUrp: {
attribute: {
name: "pop-url"
}
},
},
events: {
tap: function () { },
focus: function () { }
}
});

Type extensions must be defined element by element. A single custom element cannot extend multiple standard elements.
For, each custom element owns it own prototype, that can't be reused.
If you want to extend a button (for example), you have to write in JavaScript :
xtag.register('ajax-pop', {
extends: 'button',
...
And, in the HTML page:
<button is="ajax-pop">
...

You can do this using x-tag's delegate pseudo, and by adding a data- attribute to elements you wish to have this behavior:
<article data-pop="/path/to/content.html"></article>
And your JavaScript would be something like this:
xtag.addEvent(document.body, 'tap:delegate([data-pop])', function (e) {
var uri = this.getAttribute('data-pop');
$.get(uri).done(function (res) {
this.innerHTML = res;
}.bind(this));
});
Here's a codepen example:
http://codepen.io/jpecor-pmi/pen/Vexqyg

I believe you're going about using x-tag the wrong way. X-tag is meant to be used to implement entirely new tags; what you're trying to do is simply modify different pre-existing DOM elements. This can easily be done in pure javascript or more easily in jquery by assigning each desired element a shared class.

Related

Adding onselectionchange to vue

i'm trying to implement a text selection listener to display a toolbar for some custom options
<script>
export default {
name: "home",
created() {
document.onselectionchange = function() {
this.showMenu();
};
},
data() {
return {
...
};
},
methods: {
showMenu() {
console.log("show menu");
}
}
</script>
<style scoped>
</style>
but it still display that can't call showMenu of undefined, so i tried in this way:
created() {
vm = this;
document.onselectionchange = function() {
vm.showMenu();
};
},
so, nothing changed =(
i need to use this selectionchange because its the only listener that i can add that will handle desktop and mobile together, other method i should implement a touchup, touchdown and its not working for devices
Functions declared the classic way do have their own this. You can fix that by either explicitly binding this using Function.prototype.bind() or by using an ES6 arrow function (which does not have an own this, preserving the outer one).
The second problem is that if you have more than one of those components you've shown, each will re-assign (and thus, overwrite) the listener if you attach it using the assignment document.onselectionchange =. This would result in only the last select element working as you expect because it's the last one assigned.
To fix that, I suggest you use addEventListener() instead:
document.addEventListener('selectionchange', function() {
this.showMenu();
}.bind(this));
or
document.addEventListener('selectionchange', () => {
this.showMenu();
});
A third solution stores a reference to this and uses that in a closure:
const self = this;
document.addEventListener('selectionchange', function() {
self.showMenu();
});

access vue js variable in JQuery

Calling the strike function (after the select) function, I get the following error:
Uncaught ReferenceError: selected is not defined
methods: {
select: function(event) {
selected = event.target.id
},
strike: function(event) {
$(selected).toggleClass('strike')
}
}
This works using JavaScript, document.getElementById(selected).classList.add('strike') but not JQuery.
How to I define selected for jQuery to access?
Instead of having to query the DOM again, it'd be better if you save a reference to the actual element:
methods: {
select: function(event) {
this.selected = event.target;
},
strike: function() {
$(this.selected).toggleClass('strike');
}
}
If you don't have to support old IE browsers, you can forgo jQuery here completely by using the classList property:
methods: {
select: function(event) {
this.selected = event.target;
},
strike: function() {
this.selected.classList.toggle('strike');
}
}
Finally, there should be a way to handle all this through Vue's :class binding in the template itself. If you'd show us the template, we may help you improve it.
Because $() is expecting a CSS selector string. Add # to denote it is an id.
$("#" + selected).toggleClass('strike')

jQuery Widget Factory access options in a callback method

I'm trying to create a jQuery control using the widget factory. The idea is that I turn a button into a jQuery button, give it an icon, and register the click event for that button such that when invoked, it displays a calendar control on a textbox, whose id is passed in as an option to the widget method:
$.widget("calendarButton", {
options: {
textFieldId: ''
},
_create: function () {
this.element.button(
{
icons: {
primary: "ui-icon-calendar"
}
}).click(function () {
if (this.options.textFieldId != '') {
$(this.options.textFieldId).datetimepicker('show');
return false;
}
});
}
});
The problem with this however, is that this.options is undefined when the click handler is invoked; which makes sense since the method has a different scope. So I tried to see if there is a way to define a "static" variable which then can be accessed inside the callback method. I found this answer that explained how to create variables inside a wrapper function like this:
(function ($) {
var $options = this.options;
$.widget("calendarButton", {
options: {
textFieldId: ''
},
_create: function () {
this.element.button(
{
icons: {
primary: "ui-icon-calendar"
}
}).click(function () {
if ($options.textFieldId != '') {
$($options.textFieldId).datetimepicker('show');
return false;
}
});
}
});
})(jQuery);
But it still reports that $options is undefined. Is there a way to achieve this? I'm trying to avoid requiring the callback function be passed in since it'll be pretty much the same for all instances. Any help is appreciated.
After playing with it for a few hours, I finally came across the jQuery Proxy method which is exactly what I was looking for. I changed the code a little bit to look like this:
$.widget("calendarButton", {
options: {
textFieldId: ''
},
_create: function () {
this.element.button(
{
icons: {
primary: "ui-icon-calendar"
}
}).on("click", $.proxy(this._clickHandler, this));
},
_clickHandler: function () {
if (this.options.textFieldId != '') {
$(this.options.textFieldId).datetimepicker('show');
}
}
});
Notice that instead of implementing the click callback directly, I'm essentially creating a delegate that points to my private _clickHandler function, which itself runs on the same context as the $.widget() method (since the second argument of $.proxy(this._clickHandler, this) returns $.widget()'s context) hence availablity of the options variable inside the method.

I can't create a class based on actual HTML element

I'm trying to create a simple gallery with prototype.js and script.aculo.us. To handle left and right arrow I made this code, but it doesn't work
Gallery.Arrow = Class.create(document.createElement('a'), {
initialize: function(listener) {
this.on('click', listener);
this.addClassName('xjsl-arrow');
}
});
this.on is undefined. I tryed Class.create($(document.createElement('a')), ..., or even Element.extend(this) in the initialize function, but nothing works.
If I tryed Event.Handler(this, 'click', listener) to, but the error come from element.attachEvent inside prototype.js library.
Is it possible to create a class based on HTML element ?
Try building the Class based on the Element.Methods namespace like this
Gallery.Arrow = Class.create(Element.Methods, {
initialize: function(element,listener) {
this.on(element,'click', listener);
this.addClassName(element,'xjsl-arrow');
}
});
jsfiddle example http://jsfiddle.net/rPLa8/

Adding delay to jquery event on mouseover

I am trying to add a simple delay to a mouseover event of a child and having difficulties. (Still learning!)
This enables me to show the popup after a delay, but shows all of them simultaneously:
onmouseover='setTimeout(function() { $(\".skinnyPopup\").show(); }, 600)'
and this works to show only the popup I want with no delay:
onmouseover='$(this).children(\".skinnyPopup\").show()'
but the combination does not:
onmouseover='setTimeout(function() { $(this).children(\".skinnyPopup\").show(); }, 600)'
Any help would be appreciated. Thanks!
You need to define what this is when it executes, something like this would work:
setTimeout($.proxy(function() { $(this).children(".skinnyPopup").show(); }, this), 600)
Or just use .delay(), like this:
$(this).children(".skinnyPopup").delay(600).show(0);
Both of the above are quick fixes, I suggest you move away from inline handlers and check out an unobtrusive method (see this answer by Russ Cam for some great reasons), for example:
$(function() {
$('selector').mouseover(function() {
$(this).children(".skinnyPopup").delay(600).show(0);
});
});
It's because this is bound to the global context, not the element. Use something like the following instead:
// put this in your document head -- replace element with a selector for the elements you want
$(function () {
$(element).bind("mouseover", function () {
var e = $(this);
setTimeout(function () { e.children(".skinnyPopup").show(); }, 600);
});
});
If you're adamant about inline event handlers, the following should also work:
onmouseover='var self = this; setTimeout(function() { $(self).children(\".skinnyPopup\").show(); }, 600)'

Categories