apply / trigger not passing correct parameters - javascript

I've run into a strange problem with my jQuery code. I have a setup as follows:
(function($) {
var o = $({});
$.subscribe = function() { o.on.apply(o, arguments); };
$.publish = function() { o.trigger.apply(o, arguments); };
}(jQuery));
(function($) {
var CarrierView = {
subscriptions: function() {
$.subscribe( 'reporting.carrier.model.changed', this.renderModel );
},
renderModel: function( e, data ) {
var self = CarrierView;
}
};
var CarrierModel = {
subscriptions: function() {
$.subscribe( 'reporting.carrier.model.update', this.updateModel );
},
updateModel: function( value ) {
$.getJSON('carriers', function( data ) {
$.publish( 'reporting.carrier.model.changed', data );
});
}
};
window.CarrierView = CarrierView.init();
window.CarrierModel = CarrierModel.init();
})(jQuery);
Running a very basic pub/sub. My issue is the following:
A click event triggers the CarrierModel.updateModel method, which calls $.getJSON. The data returned is an Array[99], which is then published. When CarrierView.renderModel is called, the data there is the first element of the Array[99], an Array[5]. What am I doing incorrectly? How do I pass the whole set of data to the View?

Related

this.init is not a function jquery validation plugin in react app

I have form in my react application, which validates via jquery validation plugin.
let validator = $('form').validate({
errorClass: 'has-error',
errorElement:'label',
});
validator.form();
if ($('.has-error').length > 0) {
$('.has-error').each(function (index) {
$.validator().showErrors({prop:$(this).data('error')});
});
} else {
/*work with data*/
}
All errors messages showing fine, but every time when validation triggered, I get error in console:
this.init is not a function
And link me to code in plugin script:
$.validator = function( options, form ) {
this.settings = $.extend( true, {}, $.validator.defaults, options );
this.currentForm = form;
this.init();
};
How can I fix it?
UPD 1: below in the plugin script code i found this code:
$.extend( $.validator, {
//some code
prototype: {
init: function() {
this.labelContainer = $( this.settings.errorLabelContainer );
this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
this.submitted = {};
this.valueCache = {};
this.pendingRequest = 0;
this.pending = {};
this.invalid = {};
this.reset();
//some code
Maybe it fires error exception because of this init function?
I think the problem is in this line:
$.validator().showErrors({prop:$(this).data('error')});
$.validator function is a constructor so it must always be used with new keyword. If you call it as normal function this inside this function points to global window (or is undefined in strict mode) which doesn't have init method

selectize.js questions about a no result plugin and allowing default behaviour on link

I am using selectize for an auto suggest field, and i have used one of the no_results plugins to show a link when there is no result, and this works great for the most part, but i have a few dramas i am just not sure how to get around
I have two things i need to get help with
1st most important - How to pass variables to the plugin
I have multiple instances of selectize on the several pages, so i need to pass the vars hr_link and hr_label to the plugin so i don't have to recreate the plugin 30 times with just the those vars different
2nd - Allow link to be clicked, bypassing default behaviour
To get the links to be clickable i have used the onmousedown() and touchstart() but is there a better way to re-enable the default click on just this link in the results box.
I have spent a lot of time researching these items, so I don't think it is a duplicate
// The Plugin
Selectize.define('header_no_results', function( options ) {
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;
var ignoreKeys = [KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN];
var self = this;
var hr_link = 'http://link_to_info.com';
var hr_label = 'country';
options = $.extend({
message: ' No results found: click here to add a'+hr_label,
html: function(data) {
return '<div class="selectize-dropdown-content">' + data.message + '</div>';
}
}, options );
self.on('type', function() {
var message = 'Not Found: click here Add a '+hr_label;
if (!self.hasOptions) {
self.$empty_results_container.html(message).show();
} else {
self.$empty_results_container.hide();
}
});
self.onKeyUp = (function() {
var original = self.onKeyUp;
return function ( e ) {
if (ignoreKeys.indexOf(e.keyCode) > -1) return;
self.isOpen = false;
original.apply( self, arguments );
}
})();
self.onBlur = (function () {
var original = self.onBlur;
return function () {
original.apply( self, arguments );
self.$empty_results_container.hide();
};
})();
self.setup = (function() {
var original = self.setup;
return function() {
original.apply( self, arguments);
self.$empty_results_container = $(
options.html($.extend({
classNames: self.$input.attr( 'class' )
}, options))
);
self.$empty_results_container.hide();
self.$dropdown.append(self.$empty_results_container);
};
})();
});
// the function calling the plugin
$('#companyLinks').selectize({
valueField: 'id',
labelField: 'display',
searchField: 'display',
maxItems: 1,
options: [],
create: false,
onItemAdd: function(value){
window.location.href = 'http://my_link.com/'+value;
},
load: function(query, callback) {
if (!query.length) return callback();
$.ajax({
url: 'http://link.com/get/list',
type: 'GET',
dataType: 'json',
data: {
q: query
},
error: function() {
callback();
},
success: function(res) {
callback(res);
//window.open($(res).val(), '_self');
}
});
},
plugins: ['header_no_results']
});
The solution to pass the var was not all that hard after all just had to look in the right place, and there is further info here
In the function we need to change out
plugins: ['header_no_results']
with
plugins: { "header_no_results": {
link : "page/location",
} }
then we can retrieve link and declare the var we needed in the plugin by
var hr_link = options.link;

Cocos2d js touch events

I'm building an app in cocos2d-js, and I've got a problem with listening to keyboard events. I expect a method called setKeyboardEnabled to exists but when I call it i get an error that setKeyboardEnabled is not a function, Am I missing something?
var AnimationLayer = cc.Layer.extend({
ctor : function() {
this._super();
this.setKeyboardEnabled(true);
},
onKeyDown : function(key) {
cc.log("action");
}
...
...
)}
The same thing happens when I try to listen to touch events.
In Cocos2D v3 the way events are handled has changed. For a proper explanation of the whole system you should read New event manager in Cocos2d-Html5 v3.0.
In short, if you used to have:
var AnimationLayer = cc.Layer.extend({
ctor : function() {
this._super();
this.setKeyboardEnabled(true);
},
onKeyDown : function(key) {
cc.log("action");
}
...
...
)}
You have to turn it into something like:
var AnimationLayer = cc.Layer.extend({
ctor : function() {
this._super();
cc.eventManager.addListener({
event: cc.EventListener.KEYBOARD,
onKeyDown : function(key) {
cc.log("action");
}
}, this);
},
...
...
)}
This can sound a bit complicated at first, but this new mechanism allows you to attach these event listeners to any kind of cc node, not just layers. So for example you could do something like this to make a Sprite fade when the mouse is above it:
var hoverHandler = cc.EventListener.create({
event: cc.EventListener.MOUSE,
onMouseMove: function (event) {
var target = event.getCurrentTarget();
var locationInNode = target.convertToNodeSpace(event.getLocation());
var s = target.getContentSize();
var rect = cc.rect(0, 0, s.width, s.height);
if (cc.rectContainsPoint(rect, locationInNode)) {
cc.log("It's hovering! x = " + locationInNode.x + ", y = " + locationInNode.y);
target.opacity = 180;
return true;
} else {
target.opacity = 255;
return false;
}
}
});
var MyLayer = cc.Layer.extend({
init: function() {
this._super();
var mySpriteThatFadesWhenHovered = cc.Sprite.create(...);
this.addChild(mySpriteThatFadesWhenHovered);
cc.eventManager.addListener(hoverHandler.clone(), mySpriteThatFadesWhenHovered );
}
)}

Cannot select a dynamically added list item until it is clicked

I have written a small JQuery plugin that creates a dropdown box based on bootstrap. I have written it to where a data attribute supplies a url that produces the list items. After the ajax call, Jquery loops through the list items and inserts them into the dropdown menu. Here is what I do not understand, the plugin takes a div with the class of .combobox and appends the required html to make the combobox. It uses two functions, _create() and _listItems(). _create() actually adds the html and calls on _listItems() to make the ajax call and it returns the list items to be appended. Looks like this:
;(function ( $, window, document, undefined ) {
var Combobox = function(element,options) {
this.$element = $(element);
this.$options = $.extend({}, $.fn.combobox.defaults, options);
this.$html = {
input: $('<input type="text" placeholder="[SELECT]" />').addClass('form-control'),
button: $('<div id="test"/>').addClass('input-group-btn')
.append($('<button />')
.addClass('btn btn-default input-sm')
.append('<span class="caret"></span>'))
}
this.$list_type = this.$element.attr('data-type');
this.$url = this.$element.attr('data-url');
this.$defaultValue = this.$element.attr('data-default');
this._create();
this.$input = this.$element.find('input');
this.$button = this.$element.find('button');
this.$list = this.$element.find('ul')
this.$button.on('click',$.proxy(this._toggleList,this));
this.$element.on('click','li',$.proxy(this._itemClicked,this));
this.$element.on('mouseleave',$.proxy(this._toggleList,this));
if(this.$defaultValue) {
this.selectByValue(this.$defaultValue);
}
}
Combobox.prototype = {
constructor: Combobox,
_create: function() {
this.$element.addClass('input-group input-group-sm')
.append(this.$html.input)
.append(this._listItems())
.append(this.$html.button);
},
_itemClicked: function(e){
this.$selectedItem = $(e.target).parent();
this.$input.val(this.$selectedItem.text());
console.log(this.$element.find('[data-value="W"]'))
this._toggleList(e);
e.preventDefault();
},
_listItems: function() {
var list = $('<ul />').addClass('dropdown-menu');
$.ajax({
url: this.$url,
type: 'POST',
data: {opt: this.$list_type},
success:function(data){
$.each(data,function(key,text){
list.append($('<li class="listObjItem" data-value="'+text.id+'">'+text.value+'</li>'));
})
}
})
return list
},
selectedItem: function() {
var item = this.$selectedItem;
var data = {};
if (item) {
var txt = this.$selectedItem.text();
data = $.extend({ text: txt }, this.$selectedItem.data());
}
else {
data = { text: this.$input.val()};
}
return data;
},
selectByValue: function(value) {
var selector = '[data-value="'+value+'"]';
this.selectBySelector(selector);
},
selectBySelector: function (selector) {
var $item = this.$element.find(selector);
if (typeof $item[0] !== 'undefined') {
this.$selectedItem = $item;
this.$input.val(this.$selectedItem.text());
}
else {
this.$selectedItem = null;
}
},
enable: function () {
this.$input.removeAttr('disabled');
this.$button.children().removeClass('disabled');
this.$button.on('click',$.proxy(this._toggleList,this));
},
disable: function () {
this.$input.attr('disabled', true);
this.$button.children().addClass('disabled');
this.$button.off('click',$.proxy(this._toggleList,this));
},
_toggleList: function(e) {
if(e.type == 'mouseleave') {
if(this.$list.is(':hidden')) {
return false;
} else {
this.$list.hide();
}
} else {
this.$list.toggle();
e.preventDefault();
}
}
}
$.fn.combobox = function (option) {
return this.each(function () {
if (!$.data(this, 'combobox')) {
$.data(this, 'combobox',
new Combobox( this, option ));
}
});
};
$.fn.combobox.defaults = {};
$.fn.combobox.Constructor = Combobox;
})( jQuery, window, document );
The problem is that after the items are appended to the DOM, everything is selectable accept the list items. I currently have an .on() statement that binds the click event with the list item. To test this out I have used console.log(this.$element.find('[data-value="W"]') and it does not return an element, however if I place that same console log in the click callback of the list item it will return the element and it is selectable. Am I doing something wrong?
EDIT
I have pasted the entire plugin to save on confusion.

Call the same instance of jQuery plugin

I have written a jQuery plugin below and would like to be able to call it again for the same instance on an element.
The plugin goes...
(function($) {
$.fn.myPlugin = function(options){
var settings = {
color: null
};
if (options) {
$.extend(settings, options);
}
return this.each(function(){
var self = this;
var pics = $('li', self);
function refresh() {
pics = $('li', self);
};
$('a', self).click(function(){
pics.filter(':last').remove();
alert(settings.color);
refresh();
return false;
});
});
}
})(jQuery);
In the page this is called...
$('#test').myPlugin({ color: 'blue' });
Now I want to call the same plugin for the same instance but pass the string refresh as the option whilst all the other variables are the same (so color would still be blue) e.g...
$('#test').myPlugin('refresh');
This would then execute the refresh() function.
How could I achieve that with the above?
Edit: To make it clearer I am thinking of how jQuery UI does their plugins. In the sortable plugin you can do $("#sortable").sortable(); and then $("#sortable").sortable('refresh'); on the same element. This is what I am trying to achieve.
You can store your instance with .data() and check for it when creating an instance.
Something like:
$.fn.doStuff = function () {
var ob = $(this);
var data = ob.data();
if (data.doStuff !== undefined) {
return data.doStuff;
}
doStuff;
});
(function($) {
$.fn.myPlugin = function(options){
var init = function($self, ops){
$self.find("a").click(function(){
pics.filter(':last').remove();
alert(settings.color);
refresh();
return false;
});
};
this.refresh = function(){
//your code here
};
return this.each(function(){
var self = this;
var pics = $('li', self);
var settings = {
color: null
};
var ops = $.extend(true, settings, options);
init($(this), ops);
});
}
})(jQuery);
try something like this. and you can call refresh() like $().myPlugin().refresh();

Categories

Resources