I have a function that is working and looks like this:
var $$ = function(selector, context) {
context = context || document;
var elements = context.querySelectorAll(selector);
return Array.prototype.slice.call(elements);
}
// My function
var myFunction = function() {
$$( '.my-selector' ).forEach( function( element ) {
element.addEventListener('click', function(e){
console.log('Do something');
});
});
}
I would prefer it looks more like jQuery:
// My function
var myFunction = function() {
$('.my-selector').click(function(e) {
console.log('Do something');
});
}
I can't figure out how to do that. Any ideas?
(I want my code to be independent of frameworks so I don't want jQuery)
Solution1: with your own wrapper: Fiddler link
var $$ = function(selector, context) {
context = context || document;
var elements = context.querySelectorAll(selector);
var wrapper = function(elem){
var element = elem;
this.click = function(cb){
element.forEach(function(el){
el.addEventListener('click', function(e){
cb.apply(element,[e]);
});
});
};
};
return new wrapper(Array.prototype.slice.call(elements));
}
$$("#test").click(function(e){
console.log("Do something:"+e.type);
});
Solution 2 directly binding to native element: Fiddler link
var $$ = function(selector, context) {
context = context || document;
var elements = Array.prototype.slice.call(context.querySelectorAll(selector));
elements.click = function(cb){
elements.forEach(function(el){
el.addEventListener('click', function(e){
cb.apply(elements,[e]);
});
});
};
return elements;
}
$$("#test").click(function(e){
console.log("Do something:"+e.type);
});
Related
I have been trying to pass a variable to _F.search in this but no luck, can someone please help?
(function(window, $) {
// 'use strict';
//setInterval(function () {alert("Hello")}, 3000);
var StreamTable = function(container, opts, data) {
return new _StreamTable(container, opts, data);
};
_F.search = function(text){
alert("search " + text);
var q = $.trim(text), count = 0;
// alert(this.last_search_text);
if (q == this.last_search_text) return;
this.last_search_text = q;
if(q.length == 0 ){
this.render(0);
}else{
this.searchInData(q);
this.render(0);
}
this.current_page = 0;
this.renderPagination(this.pageCount(), this.current_page);
this.execCallbacks('pagination');
};
}
I tried
onclick ="window.search(5)"
from a click button but still did not work.
The search function should be declared like this:
window.search = function(text){
This will attach the search function to the window object. This will allow you to attach it to the onclick event, like you have in your example:
onclick="window.search(5)"
I have an revealing patterned applied class.How can I reach btnMenu event outside of the model
thanks.
MyModel= (function () {
var btnClickEvents = function () {
var btnMenu = $('.btnMenu').on('click', function () {
var date= $(this).attr("data-rezerve-date");
var statu= $(this).attr("data-rezerve-statu");
alert("click"+date+'---'+statu);
});
};
return {
initialize: initialize,
asignValues: asignValues,
getRezervationDateAndStatus: btnClickEvents.btnMenu//how can I reach this function outside of model
};
})();
update
I change my code as u show.and add one return function
MyModel = (function () {
var dt = "";
var statu = "";
var rvalue = {};
var btnClickEvents = function () {
$('.btnMenu').on('click', onBtnMenuClick);
};
function onBtnMenuClick(e) {
dt = $(this).attr("data-rezerve-date");
statu = $(this).attr("data-rezerve-statu");
rvalue.date = dt;
rvalue.statu = statu;
console.log(dt);
}
var getRezervationDateAndStatus = function () {
return rvalue;
};
return {
initialize: initialize,
asignValues: asignValues,
getRezervationDateAndStatus: getRezervationDateAndStatus
};
})();
and after include my module to my web page calling is like this,
MyModel.asignValues(rezervasyonTable,data);
MyModel.initialize();
var result = MyModel.getRezervationDateAndStatus();
console.log(result.date);
bu console log empty.
As you say it is a " revealing" pattern. You could see what you expose. To be able to use this function outside of the module change your code like this:
MyModel = (function () {
var btnClickEvents = function () {
$('.btnMenu').on('click', onBtnMenuClick);
};
function onBtnMenuClick(e) {
var date = $(this).attr("data-rezerve-date");
var statu = $(this).attr("data-rezerve-statu");
alert("click" + date + '---' + statu);
}
return {
initialize: initialize,
asignValues: asignValues,
getRezervationDateAndStatus: onBtnMenuClick
};
})();
on my website I have a div .toggle-search that if you click on it it expands to .search-expand where a search form is. This is the code in jQuery
/* Toggle header search
/* ------------------------------------ */
$('.toggle-search').click(function(){
$('.toggle-search').toggleClass('active');
$('.search-expand').fadeToggle(250);
setTimeout(function(){
$('.search-expand input').focus();
}, 300);
});
Now the only way to close the .search-expand is to click once again on the .toggle-search. But I want to change that it closes if you click anywhere else on the site. For an easier example I have the Hueman theme, and I'm talking about the top right corner search option. http://demo.alxmedia.se/hueman/
Thanks!
Add the event on all elements except the search area.
$('body *:not(".search-expand")').click(function(){
$('.toggle-search').removeClass('active');
$('.search-expand').fadeOut(250);
});
or another way,
$('body').click(function(e){
if(e.target.className.indexOf('search-expand') < 0){
$('.toggle-search').removeClass('active');
$('.search-expand').fadeOut(250);
}
});
var isSearchFieldOpen = false;
var $toggleSearch = $('.toggle-search');
var $searchExpand = $('.search-expand');
function toggleSearch() {
// Reverse state
isSearchFieldOpen = !isSearchFieldOpen;
$toggleSearch.toggleClass('active');
// You can use callback function instead of using setTimeout
$searchExpand.fadeToggle(250, function() {
if (isSearchFieldOpen) {
$searchExpand.find('input').focus();
}
});
}
$toggleSearch.on('click', function(e) {
e.stopPropagation();
toggleSearch();
});
$(document.body).on('click', function(e) {
if (isSearchFieldOpen) {
var target = e.target;
// Checking if user clicks outside .search-expand
if (!$searchExpand.is(target) && !$searchExpand.has(target).length) {
toggleSearch();
}
}
});
I have a second search on the site with the same code as before only
with div .toggle-serach2 and .expand-search2, how can i make your code
so it wont overlap. just changing the name to $('toggle-search2')
doesn't cut it
in that case, I would suggest you convert your code into a plugin:
(function($, document) {
var bodyHandlerAttached = false;
var openedForms = [];
var instances = {};
var defaults = {
activeClass: 'active'
};
function ToggleSearch(elem, options) {
this.options = $.extend({}, defaults, options);
this.$elem = $(elem);
this.$btn = $(options.toggleBtn);
this.isOpen = false;
this.id = generateId();
this.bindEvents();
instances[this.id] = this;
if (!bodyHandlerAttached) {
handleOutsideClick();
bodyHandlerAttached = true;
}
}
ToggleSearch.prototype = {
bindEvents: function() {
this.$btn.on('click', $.proxy(toggleHandler, this));
},
open: function() {
if (this.isOpen) { return; }
var _this = this;
this.$btn.addClass(this.options.activeClass);
this.$elem.fadeIn(250, function() {
_this.$elem.find('input').focus();
});
openedForms.push(this.id);
this.isOpen = true;
},
close: function(instantly) {
if (!this.isOpen) { return; }
this.$btn.removeClass(this.options.activeClass);
if (instantly) {
this.$elem.hide();
} else {
this.$elem.fadeOut(250);
}
openedForms.splice(openedForms.indexOf(this.id), 1);
this.isOpen = false;
},
toggle: function() {
if (this.isOpen) {
this.close();
} else {
this.open();
}
}
};
var toggleHandler = function(ev) {
ev.stopPropagation();
this.toggle();
};
var handleOutsideClick = function(e) {
$(document.body).on('click', function(e) {
if (openedForms.length) {
var target = e.target;
var instance;
for (var id in instances) {
instance = instances[id];
if (!instance.$elem.is(target) && !instance.$elem.has(target).length) {
instance.close(true);
}
}
}
});
};
function generateId() {
return Math.random().toString(36).substr(2, 8);
}
$.fn.toggleSearch = function(options) {
return this.each(function() {
if (!$.data(this, 'toggleSearch')) {
$.data(this, 'toggleSearch', new ToggleSearch(this, options));
}
});
};
})(window.jQuery, document);
And then use it like this:
$('.search-expand').toggleSearch({
toggleBtn: '.toggle-search'
});
$('.search-expand2').toggleSearch({
toggleBtn: '.toggle-search2'
});
JSFiddle example
You could add a click handler to the main window that removes the active class:
$(window).click(function(){
$('.toggle-search').removeClass('active');
}
and then prevent the class removal when you click inside of your toggle-search elem
$('.toggle-search').click(function(e){
e.stopPropagation();
// remainder of click code here
)};
Try to add body click listener
$('body').click(function(e){
if ($(e.target).is('.toggle-search')) return;
$('.toggle-search').removeClass('active');
$('.search-expand').fadeOut(250);
});
I have started jQuery plugin where I want to retrieve the .duration and .currentTime on a HTML5 video, from within a bound .on('click', ) event.
I am struggling to capture this information within my plugin.registerClick function, here is my code:
(function ($) {
$.myPlugin = function (element, options) {
var defaults = {
videoOnPage: 0,
dataSource: 'data/jsonIntervals.txt',
registerClick: function () { }
}
var plugin = this;
plugin.settings = {}
var $element = $(element);
element = element;
plugin.init = function () {
plugin.settings = $.extend({}, defaults, options);
$element.on('click', plugin.registerClick);
getJsonIntervals();
}
plugin.registerClick = function () {
var duration = $('video').get(plugin.settings.videoOnPage).duration;
console.log('duration: ' + duration);
}
var startTimes = [];
var dataSet = false;
var getJsonIntervals = function () {
if (dataSet == false) {
//calls a $.getJSON method.
//populates startTimes
//updates dataSet = true;
};
}
plugin.init();
}
$.fn.myPlugin = function (options) {
return this.each(function () {
if (undefined == $(this).data('myPlugin')) {
var plugin = new $.myPlugin(this, options);
$(this).data('myPlugin', plugin);
}
})
};
})(jQuery);
$(function () {
$('#button1').myPlugin();
});
Here my sample jsFiddle Click Here
Seems to work for me:
plugin.registerClick = function () {
var video = $('video').get(0);
console.log('duration: ' + video.duration);
console.log('currenttime: ' + video.currentTime);
}
http://jsfiddle.net/p4w040uz/2/
You need to play the video first then click the button. The browser has to retrieve the meta data first before it can return it.
Additional reference material you can read up:
http://www.w3schools.com/tags/av_event_loadedmetadata.asp
http://www.w3.org/2010/05/video/mediaevents.html
I can't figure out why this isn't working. The cThis.menuClick doesn't recieve the event, it does get called though.
// no event passed to cThis.menuClick
var Menu = new function() {
var cThis = this;
// .....
cThis.menuItems = cThis.element.querySelectorAll('#menu-items a.menu-item');
for(var i=0; i<cThis.menuItems.length; i++) {
cThis.menuItems[i].addEventListener('click', cThis.menuClick, false);
}
cThis.menuClick = function(event, returning) {
if (event) { event.preventDefault(); }
// not prevented
}
}
I solved the issue this way:
// event passed, working!
var Menu = new function() {
var cThis = this;
// .....
cThis.menuItems = cThis.element.querySelectorAll('#menu-items a.menu-item');
for(var i=0; i<cThis.menuItems.length; i++) {
cThis.menuItems[i].addEventListener('click', mC, false);
}
function mC(event) {
cThis.menuClick.call(this, event);
}
cThis.menuClick = function(event, returning) {
if (event) { event.preventDefault(); }
// prevented
}
}
Although this workaround is working, I whould like to know why the first code isn't?
Code is wrapped in a namespace:
var NS = new function() {
}
menuClick is not defined when the event is attached. Simply assign the function to the menuclick property prior to registering it with the event listener.
var Menu = new function() {
var cThis = this;
// .....
cThis.menuItems = cThis.element.querySelectorAll('#menu-items a.menu-item');
cThis.menuClick = function(event, returning) {
if (event) { event.preventDefault(); }
// not prevented
}
for(var i=0; i<cThis.menuItems.length; i++) {
cThis.menuItems[i].addEventListener('click', cThis.menuClick, false);
}
}