I have created a plug-in popup and trying to create reference and access the public method of the plug-in but it is giving an error 'Undefined Function'.
var pop = $('.divCls').popup();
pop.setTitle('Sample Text');//This is line giving error
Here is my plug-in
(function ($) {
$.widget('bs.popup', {
options:{
// containment: '.bs-editor-body',
hideOnClick: '.bs-editor-body',
showTimeDelay:0
},
_create: function (){
var me = this,
el = me.element,
opts = me.options;
el.addClass('bs-popup');
el.html($('<div class="bs-popup-body">' + el.html() + '</div>'));
el.body = el.find('.bs-popup-body');
me._refresh();
if(opts.draggable){
el.draggable({containment:'document',cancel:'.bs-popup-body'});
el.unbind().bind('click',function(event){
event.stopPropagation();
});
}
$(document).on('click','body',function(){
me.hide();
});
me.show();
},
_init:function(){
this.show();
this._refresh();
},
_refresh:function(){
var me = this,
el = me.element,
opts = me.options;
el.find('.bs-popup-header').remove();
if(opts.title && opts.title !='') {
el.prepend('<div class="bs-popup-header"></div>');
el.hdr = el.find('.bs-popup-header');
me.setTitle(opts.title);
el.body.css({'border-top-left-radius':0,'border-top-right-radius':0})
} else {
el.body.css({'border-radius': el.body.css('border-bottom-left-radius')})
}
if(opts.width)me.setWidth(opts.width);
if(opts.height)me.setHeight(opts.height);
if(opts.left && opts.top) me.setXY(opts.left ,opts.top);
if(opts.cls) el.addClass(opts.cls);
},
show: function () {
debugger;
this.hide();
this.element.show(this.options.showTimeDelay);
},
hide: function () {
this.element.hide();
this._destroy();
},
setTitle:function(title){
this.getHeader().text(title);
},
setXY: function (x,y){
var me = this,
el = me.getElement(),
opts = me.options;
if (x && y) {
el.css({'left': x, top: y});
} else {
// var confine = evtRef.closest(opts.containment);
}
},
setWidth: function (value){
this.getBody().css({width: value});
},
setHeight: function (value) {
this.getBody().css({height: value});
},
getElement:function(){
return this.element;
},
getHeader:function(){
return this.element.hdr;
},
getBody:function(){
return this.element.body;
},
_destroy:function(){
// $.Widget.prototype.destroy.call(this);
}
});
}(jQuery));
You can try
pop.popup('setTitle', 'Sample Text');
Widget Method Invocation
To invoke a method using the widget's plugin, pass the name of the
method as a string.
Widget Public Methods
Related
I am using Leaflet and it works well. I am using leaflet.label as well and that works nicely as well. The problem is that I would like to display two labels to the right of the marker. If I call bindLabel twice, then the second overrides the first. How could I make sure that I have two labels, both to the right of the marker and the second label is above the first one?
This is how I tried:
newMarker.bindLabel(result, { noHide: true }).bindLabel("secondlabel", { noHide: true });
Thanks
EDIT:
I have managed to display the texts using a single call to bindLabel, like this:
newMarker.bindLabel(result + "<br>secondLabel", { noHide: true });
but this seems to be a too hacky solution.
Here they say it is not possible, but that was written in 2014. It might be possible since then.
I have managed to solve it. I am lazy to push it to their repo right now, but I will probably do it in the future. The logic of the solution is as follows:
this.label -> this.labels
this.labels is an array of LeafletLabels
apply the change for methods containing this.label
move this._labelNoHide = options.noHide into the if to prevent bugs
The labels will act similarly for the subset of options which is handled singularly / marker. Sorry, folks, singularizing noHide or opacity to label level instead of marker level is beyond the scope of this question. I might resolve those later though.
The code is as follows:
/*
Leaflet.label, a plugin that adds labels to markers and vectors for Leaflet powered maps.
(c) 2012-2013, Jacob Toye, Smartrak
https://github.com/Leaflet/Leaflet.label
http://leafletjs.com
https://github.com/jacobtoye
*/
(function (factory, window) {
// define an AMD module that relies on 'leaflet'
if (typeof define === 'function' && define.amd) {
define(['leaflet'], factory);
// define a Common JS module that relies on 'leaflet'
} else if (typeof exports === 'object') {
module.exports = factory(require('leaflet'));
}
// attach your plugin to the global 'L' variable
if (typeof window !== 'undefined' && window.L) {
window.LeafletLabel = factory(L);
}
}(function (L) {
L.labelVersion = '0.2.4';
var LeafletLabel = L.Class.extend({
includes: L.Mixin.Events,
options: {
className: '',
clickable: false,
direction: 'right',
noHide: false,
offset: [12, -15], // 6 (width of the label triangle) + 6 (padding)
opacity: 1,
zoomAnimation: true
},
initialize: function (options, source) {
L.setOptions(this, options);
this._source = source;
this._animated = L.Browser.any3d && this.options.zoomAnimation;
this._isOpen = false;
},
onAdd: function (map) {
this._map = map;
this._pane = this.options.pane ? map._panes[this.options.pane] :
this._source instanceof L.Marker ? map._panes.markerPane : map._panes.popupPane;
if (!this._container) {
this._initLayout();
}
this._pane.appendChild(this._container);
this._initInteraction();
this._update();
this.setOpacity(this.options.opacity);
map
.on('moveend', this._onMoveEnd, this)
.on('viewreset', this._onViewReset, this);
if (this._animated) {
map.on('zoomanim', this._zoomAnimation, this);
}
if (L.Browser.touch && !this.options.noHide) {
L.DomEvent.on(this._container, 'click', this.close, this);
map.on('click', this.close, this);
}
},
onRemove: function (map) {
this._pane.removeChild(this._container);
map.off({
zoomanim: this._zoomAnimation,
moveend: this._onMoveEnd,
viewreset: this._onViewReset
}, this);
this._removeInteraction();
this._map = null;
},
setLatLng: function (latlng) {
this._latlng = L.latLng(latlng);
if (this._map) {
this._updatePosition();
}
return this;
},
setContent: function (content) {
// Backup previous content and store new content
this._previousContent = this._content;
this._content = content;
this._updateContent();
return this;
},
close: function () {
var map = this._map;
if (map) {
if (L.Browser.touch && !this.options.noHide) {
L.DomEvent.off(this._container, 'click', this.close);
map.off('click', this.close, this);
}
map.removeLayer(this);
}
},
updateZIndex: function (zIndex) {
this._zIndex = zIndex;
if (this._container && this._zIndex) {
this._container.style.zIndex = zIndex;
}
},
setOpacity: function (opacity) {
this.options.opacity = opacity;
if (this._container) {
L.DomUtil.setOpacity(this._container, opacity);
}
},
_initLayout: function () {
this._container = L.DomUtil.create('div', 'leaflet-label ' + this.options.className + ' leaflet-zoom-animated');
this.updateZIndex(this._zIndex);
},
_update: function () {
if (!this._map) { return; }
this._container.style.visibility = 'hidden';
this._updateContent();
this._updatePosition();
this._container.style.visibility = '';
},
_updateContent: function () {
if (!this._content || !this._map || this._prevContent === this._content) {
return;
}
if (typeof this._content === 'string') {
this._container.innerHTML = this._content;
this._prevContent = this._content;
this._labelWidth = this._container.offsetWidth;
}
},
_updatePosition: function () {
var pos = this._map.latLngToLayerPoint(this._latlng);
this._setPosition(pos);
},
_setPosition: function (pos) {
var map = this._map,
container = this._container,
centerPoint = map.latLngToContainerPoint(map.getCenter()),
labelPoint = map.layerPointToContainerPoint(pos),
direction = this.options.direction,
labelWidth = this._labelWidth,
offset = L.point(this.options.offset);
// position to the right (right or auto & needs to)
if (direction === 'right' || direction === 'auto' && labelPoint.x < centerPoint.x) {
L.DomUtil.addClass(container, 'leaflet-label-right');
L.DomUtil.removeClass(container, 'leaflet-label-left');
pos = pos.add(offset);
} else { // position to the left
L.DomUtil.addClass(container, 'leaflet-label-left');
L.DomUtil.removeClass(container, 'leaflet-label-right');
pos = pos.add(L.point(-offset.x - labelWidth, offset.y));
}
L.DomUtil.setPosition(container, pos);
},
_zoomAnimation: function (opt) {
var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
this._setPosition(pos);
},
_onMoveEnd: function () {
if (!this._animated || this.options.direction === 'auto') {
this._updatePosition();
}
},
_onViewReset: function (e) {
/* if map resets hard, we must update the label */
if (e && e.hard) {
this._update();
}
},
_initInteraction: function () {
if (!this.options.clickable) { return; }
var container = this._container,
events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu'];
L.DomUtil.addClass(container, 'leaflet-clickable');
L.DomEvent.on(container, 'click', this._onMouseClick, this);
for (var i = 0; i < events.length; i++) {
L.DomEvent.on(container, events[i], this._fireMouseEvent, this);
}
},
_removeInteraction: function () {
if (!this.options.clickable) { return; }
var container = this._container,
events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu'];
L.DomUtil.removeClass(container, 'leaflet-clickable');
L.DomEvent.off(container, 'click', this._onMouseClick, this);
for (var i = 0; i < events.length; i++) {
L.DomEvent.off(container, events[i], this._fireMouseEvent, this);
}
},
_onMouseClick: function (e) {
if (this.hasEventListeners(e.type)) {
L.DomEvent.stopPropagation(e);
}
this.fire(e.type, {
originalEvent: e
});
},
_fireMouseEvent: function (e) {
this.fire(e.type, {
originalEvent: e
});
// TODO proper custom event propagation
// this line will always be called if marker is in a FeatureGroup
if (e.type === 'contextmenu' && this.hasEventListeners(e.type)) {
L.DomEvent.preventDefault(e);
}
if (e.type !== 'mousedown') {
L.DomEvent.stopPropagation(e);
} else {
L.DomEvent.preventDefault(e);
}
}
});
/*global LeafletLabel */
// This object is a mixin for L.Marker and L.CircleMarker. We declare it here as both need to include the contents.
L.BaseMarkerMethods = {
showLabel: function () {
if (this.labels && this._map) {
for (var labelIndex in this.labels) {
this.labels[labelIndex].setLatLng(this._latlng);
this._map.showLabel(this.labels[labelIndex]);
}
}
return this;
},
hideLabel: function () {
if (this.labels) {
for (var labelIndex in this.labels) {
this.labels[labelIndex].close();
}
}
return this;
},
setLabelNoHide: function (noHide) {
if (this._labelNoHide === noHide) {
return;
}
this._labelNoHide = noHide;
if (noHide) {
this._removeLabelRevealHandlers();
this.showLabel();
} else {
this._addLabelRevealHandlers();
this.hideLabel();
}
},
bindLabel: function (content, options) {
var labelAnchor = this.options.icon ? this.options.icon.options.labelAnchor : this.options.labelAnchor,
anchor = L.point(labelAnchor) || L.point(0, 0);
anchor = anchor.add(LeafletLabel.prototype.options.offset);
if (options && options.offset) {
anchor = anchor.add(options.offset);
}
options = L.Util.extend({ offset: anchor }, options);
if (!this.labels) {
this._labelNoHide = options.noHide;
this.labels = [];
if (!this._labelNoHide) {
this._addLabelRevealHandlers();
}
this
.on('remove', this.hideLabel, this)
.on('move', this._moveLabel, this)
.on('add', this._onMarkerAdd, this);
this._hasLabelHandlers = true;
}
this.labels.push(new LeafletLabel(options, this).setContent(content));
return this;
},
unbindLabel: function () {
if (this.labels) {
this.hideLabel();
this.labels = null;
if (this._hasLabelHandlers) {
if (!this._labelNoHide) {
this._removeLabelRevealHandlers();
}
this
.off('remove', this.hideLabel, this)
.off('move', this._moveLabel, this)
.off('add', this._onMarkerAdd, this);
}
this._hasLabelHandlers = false;
}
return this;
},
updateLabelContent: function (content, index) {
if ((this.labels) && (index < this.labels.length)) {
this.labels[index].setContent(content);
}
},
getLabels: function () {
return this.labels;
},
_onMarkerAdd: function () {
if (this._labelNoHide) {
this.showLabel();
}
},
_addLabelRevealHandlers: function () {
this
.on('mouseover', this.showLabel, this)
.on('mouseout', this.hideLabel, this);
if (L.Browser.touch) {
this.on('click', this.showLabel, this);
}
},
_removeLabelRevealHandlers: function () {
this
.off('mouseover', this.showLabel, this)
.off('mouseout', this.hideLabel, this);
if (L.Browser.touch) {
this.off('click', this.showLabel, this);
}
},
_moveLabel: function (e) {
this.label.setLatLng(e.latlng);
}
};
// Add in an option to icon that is used to set where the label anchor is
L.Icon.Default.mergeOptions({
labelAnchor: new L.Point(9, -20)
});
// Have to do this since Leaflet is loaded before this plugin and initializes
// L.Marker.options.icon therefore missing our mixin above.
L.Marker.mergeOptions({
icon: new L.Icon.Default()
});
L.Marker.include(L.BaseMarkerMethods);
L.Marker.include({
_originalUpdateZIndex: L.Marker.prototype._updateZIndex,
_updateZIndex: function (offset) {
var zIndex = this._zIndex + offset;
this._originalUpdateZIndex(offset);
if (this.labels) {
for (var labelIndex in this.labels) {
this.labels[labelIndex].updateZIndex(zIndex);
}
}
},
_originalSetOpacity: L.Marker.prototype.setOpacity,
setOpacity: function (opacity, labelHasSemiTransparency) {
this.options.labelHasSemiTransparency = labelHasSemiTransparency;
this._originalSetOpacity(opacity);
},
_originalUpdateOpacity: L.Marker.prototype._updateOpacity,
_updateOpacity: function () {
var absoluteOpacity = this.options.opacity === 0 ? 0 : 1;
this._originalUpdateOpacity();
if (this.labels) {
for (var labelIndex in labels) {
this.labels[labelIndex].setOpacity(this.options.labelHasSemiTransparency ? this.options.opacity : absoluteOpacity);
}
}
},
_originalSetLatLng: L.Marker.prototype.setLatLng,
setLatLng: function (latlng) {
if (this.labels && !this._labelNoHide) {
this.hideLabel();
}
return this._originalSetLatLng(latlng);
}
});
// Add in an option to icon that is used to set where the label anchor is
L.CircleMarker.mergeOptions({
labelAnchor: new L.Point(0, 0)
});
L.CircleMarker.include(L.BaseMarkerMethods);
/*global LeafletLabel */
L.Path.include({
bindLabel: function (content, options) {
if (!this.label || this.label.options !== options) {
this.label = new LeafletLabel(options, this);
}
this.label.setContent(content);
if (!this._showLabelAdded) {
this
.on('mouseover', this._showLabel, this)
.on('mousemove', this._moveLabel, this)
.on('mouseout remove', this._hideLabel, this);
if (L.Browser.touch) {
this.on('click', this._showLabel, this);
}
this._showLabelAdded = true;
}
return this;
},
unbindLabel: function () {
if (this.label) {
this._hideLabel();
this.label = null;
this._showLabelAdded = false;
this
.off('mouseover', this._showLabel, this)
.off('mousemove', this._moveLabel, this)
.off('mouseout remove', this._hideLabel, this);
}
return this;
},
updateLabelContent: function (content) {
if (this.label) {
this.label.setContent(content);
}
},
_showLabel: function (e) {
this.label.setLatLng(e.latlng);
this._map.showLabel(this.label);
},
_moveLabel: function (e) {
this.label.setLatLng(e.latlng);
},
_hideLabel: function () {
this.label.close();
}
});
L.Map.include({
showLabel: function (label) {
return this.addLayer(label);
}
});
L.FeatureGroup.include({
// TODO: remove this when AOP is supported in Leaflet, need this as we cannot put code in removeLayer()
clearLayers: function () {
this.unbindLabel();
this.eachLayer(this.removeLayer, this);
return this;
},
bindLabel: function (content, options) {
return this.invoke('bindLabel', content, options);
},
unbindLabel: function () {
return this.invoke('unbindLabel');
},
updateLabelContent: function (content) {
this.invoke('updateLabelContent', content);
}
});
return LeafletLabel;
}, window));
I`m trying to understand jQuery plugins and how to reference objects within other functions. So, I have this:
(function($) {
var methods = {
init: function (options) {
return this.each(function () {
var defaults = {
var1 : 'variable1',
var2 : 'variable2'
};
this.settings = $.extend(defaults,options);
});
},
add: function () {
// Access settings object here...how??
alert(this.settings.var1); ????
}
};
jQuery.fn.pluginName = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this,arguments);
} else {
console.error('Method '+method+' does not exist in plugin. Plugin aborted.');
}
};
}(jQuery));
So, my question is, once I have initialised the plugin, how can I reference the settings object inside the 'add' function when the 'add' function is called?
Thank you very much for any assistance.
The problem is the context value of this.
(function($) {
var methods = {
init: function(options) {
return this.each(function() {
var defaults = {
var1: 'variable1',
var2: 'variable2'
};
//here this is the dom object not the wrapping jQuery object
this.settings = $.extend(defaults, options);
});
},
add: function() {
//here this is the jQuery object
return this.each(function() {
//here this is again the dom object
console.log(this.settings.var1);
})
}
};
jQuery.fn.pluginName = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
console.error('Method ' + method + ' does not exist in plugin. Plugin aborted.');
}
};
}(jQuery));
$('div').pluginName({
var1: 'x'
});
$('div').pluginName('add')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
I would recommend using the data api instead of attaching the settings object directly to the dom element reference
One basic boilerplate that I use for plugins is
(function($) {
function PluginName(el, settings) {
//your initialization code goes here
this.$el = $(el);
this.settings = $.extend({}, jQuery.fn.pluginName.defaults, settings);
}
PluginName.prototype.add = function() {
console.log('add', this, arguments);
}
PluginName.prototype.result = function() {
console.log('result', this, arguments);
return 'result'
}
PluginName.prototype._add = function() {
console.log('not called');
}
jQuery.fn.pluginName = function(method) {
var result, args = arguments;
this.each(function() {
var $this = $(this),
data = $this.data('pluginName');
if (data) {
if (/^[^_]/.test(method) && typeof data[method] == 'function') {
result = data[method].apply(data, Array.prototype.slice.call(args, 1));
if (result !== undefined) {
return false;
}
} else {
throw new Error('Unable to find the method ' + method);
}
} else if (typeof method == 'object') {
data = new PluginName(this, method);
$this.data('pluginName', data);
} else {
throw new Error('Illegal arguments passed');
}
})
return result === undefined ? this : result;
};
jQuery.fn.pluginName.defaults = {
var1: 'variable1',
var2: 'variable2'
};
}(jQuery));
$('div').pluginName({
var1: 'x'
});
try {
$('div').pluginName('add', 3, 5)
} catch (e) {
console.log(e);
}
try {
$('div').pluginName('add2', 3, 5)
} catch (e) {
console.log(e);
}
try {
$('div').pluginName('_add', 3, 5)
} catch (e) {
console.log(e);
}
try {
var x = $('div').pluginName('result', 3, 5);
console.log(x)
} catch (e) {
console.log(e);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div></div>
<div></div>
I have recently started using JsFormValidatorBundle to validate my forms on symfony. The only issue is that i need to send these forms with Ajax and unfortunately for some reason the JsFormValidatorBundle forces the form to be sent by reloading the page.
So now i am trying to override that function which looks like:
function FpJsCustomizeMethods() {
...
this.submitForm = function (event) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
var element = item.jsFormValidator;
if (event) {
event.preventDefault();
}
element.validateRecursively();
if (FpJsFormValidator.ajax.queue) {
if (event) {
event.preventDefault();
}
FpJsFormValidator.ajax.callbacks.push(function () {
element.onValidate.apply(element.domNode, [FpJsFormValidator.getAllErrors(element, {}), event]);
if (element.isValid()) {
item.submit();
}
});
} else {
element.onValidate.apply(element.domNode, [FpJsFormValidator.getAllErrors(element, {}), event]);
if (element.isValid()) {
item.submit();
}
}
});
};
....
}
if i remove the item.submit() it works perfectly.
So how can override this?
full script
You just need to make a new function and extend the parent via its prototype.
Perhaps this code block can explain what you need to do.
function Parent() {
this.a = function() {
alert("i am here");
}
this.submitForm = function() {
alert("i am wrong one here");
}
}
function Child () {
//we need to override function submitForm with right one
this.submitForm = function() {
alert("i am right one here");
}
}
Child.prototype = new Parent;
var c = new Child();
//other parent methods are still accessible.
c.a();
//method submitForm is overriden with the one we defined
c.submitForm();
see it in action here
As I suggested you actually don't want to overwrite the FpJsFormValidator.customizeMethods.submitForm function just to be able to submit your forms via Ajax instead of default. Doing so will result in:
code duplication as you would be forced to restore all of the validation parts in your own function
and if part of your solution would be getting rid of the item.submit() bits then you would also lose any other events bound to be driggered by that submit as a by product.
I would instead simply create a handler for the submit event on that item which would call event.preventDefault() and do the Ajax request. As you tagged your question with jQuery, something like:
$("#your_fav_form_selector").submit(function (e) {
e.preventDefault();
// fetch form data and send it off with $.ajax etc
});
There's 2 ways of doing that.
As far as I know, the function you want to override isn't a jQuery function. I kept the 2 examples so that you can decide which one fits in your code.
If it's a JavaScript function (custom or native)
First of all, I saw the function you're using and I find that it's hard to override a specific part of it, so I wrote it again and removed (or commented out) the "submit call" and then I've overridden the function. When calling FpJsFormValidator, the following function will be called NewFpJsCustomizeMethods.
<script type="text/javascript">
FpJsFormValidator = function() {
return NewFpJsCustomizeMethods();
}
function NewFpJsCustomizeMethods() {
this.init = function (options) {
FpJsFormValidator.each(this, function (item) {
if (!item.jsFormValidator) {
item.jsFormValidator = {};
}
for (var optName in options) {
switch (optName) {
case 'customEvents':
options[optName].apply(item);
break;
default:
item.jsFormValidator[optName] = options[optName];
break;
}
}
}, false);
return this;
};
this.validate = function (opts) {
var isValid = true;
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
var method = (opts && true === opts['recursive'])
? 'validateRecursively'
: 'validate';
var validateUnique = (!opts || false !== opts['findUniqueConstraint']);
if (validateUnique && item.jsFormValidator.parent) {
var data = item.jsFormValidator.parent.data;
if (data['entity'] && data['entity']['constraints']) {
for (var i in data['entity']['constraints']) {
var constraint = data['entity']['constraints'][i];
if (constraint instanceof FpJsFormValidatorBundleFormConstraintUniqueEntity && constraint.fields.indexOf(item.name)) {
var owner = item.jsFormValidator.parent;
constraint.validate(null, owner);
}
}
}
}
if (!item.jsFormValidator[method]()) {
isValid = false;
}
});
return isValid;
};
this.showErrors = function (opts) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
item.jsFormValidator.errors[opts['sourceId']] = opts['errors'];
item.jsFormValidator.showErrors.apply(item, [opts['errors'], opts['sourceId']]);
});
};
this.submitForm = function (event) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
var element = item.jsFormValidator;
if (event) {
event.preventDefault();
}
element.validateRecursively();
if (FpJsFormValidator.ajax.queue) {
if (event) {
event.preventDefault();
}
FpJsFormValidator.ajax.callbacks.push(function () {
element.onValidate.apply(element.domNode, [FpJsFormValidator.getAllErrors(element, {}), event]);
if (element.isValid()) {
//item.submit();
}
});
} else {
element.onValidate.apply(element.domNode, [FpJsFormValidator.getAllErrors(element, {}), event]);
if (element.isValid()) {
//item.submit();
}
}
});
};
this.get = function () {
var elements = [];
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
elements.push(item.jsFormValidator);
});
return elements;
};
//noinspection JSUnusedGlobalSymbols
this.addPrototype = function(name) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
var prototype = FpJsFormValidator.preparePrototype(
FpJsFormValidator.cloneObject(item.jsFormValidator.prototype),
name,
item.jsFormValidator.id + '_' + name
);
item.jsFormValidator.children[name] = FpJsFormValidator.createElement(prototype);
item.jsFormValidator.children[name].parent = item.jsFormValidator;
});
};
//noinspection JSUnusedGlobalSymbols
this.delPrototype = function(name) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
delete (item.jsFormValidator.children[name]);
});
};
}
</script>
If it's a jQuery function
First of all, I saw the function you're using and I find that it's hard to override a specific part of it, so I wrote it again and removed (or commented out) the "submit call" and then I've overridden the jQuery function. When calling FpJsFormValidator, the following function will be called NewFpJsCustomizeMethods.
Here's the code:
<script type="text/javascript">
(function(){
// Define overriding method
jQuery.fn.FpJsFormValidator = NewFpJsCustomizeMethods();
})();
function NewFpJsCustomizeMethods() {
this.init = function (options) {
FpJsFormValidator.each(this, function (item) {
if (!item.jsFormValidator) {
item.jsFormValidator = {};
}
for (var optName in options) {
switch (optName) {
case 'customEvents':
options[optName].apply(item);
break;
default:
item.jsFormValidator[optName] = options[optName];
break;
}
}
}, false);
return this;
};
this.validate = function (opts) {
var isValid = true;
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
var method = (opts && true === opts['recursive'])
? 'validateRecursively'
: 'validate';
var validateUnique = (!opts || false !== opts['findUniqueConstraint']);
if (validateUnique && item.jsFormValidator.parent) {
var data = item.jsFormValidator.parent.data;
if (data['entity'] && data['entity']['constraints']) {
for (var i in data['entity']['constraints']) {
var constraint = data['entity']['constraints'][i];
if (constraint instanceof FpJsFormValidatorBundleFormConstraintUniqueEntity && constraint.fields.indexOf(item.name)) {
var owner = item.jsFormValidator.parent;
constraint.validate(null, owner);
}
}
}
}
if (!item.jsFormValidator[method]()) {
isValid = false;
}
});
return isValid;
};
this.showErrors = function (opts) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
item.jsFormValidator.errors[opts['sourceId']] = opts['errors'];
item.jsFormValidator.showErrors.apply(item, [opts['errors'], opts['sourceId']]);
});
};
this.submitForm = function (event) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
var element = item.jsFormValidator;
if (event) {
event.preventDefault();
}
element.validateRecursively();
if (FpJsFormValidator.ajax.queue) {
if (event) {
event.preventDefault();
}
FpJsFormValidator.ajax.callbacks.push(function () {
element.onValidate.apply(element.domNode, [FpJsFormValidator.getAllErrors(element, {}), event]);
if (element.isValid()) {
//item.submit();
}
});
} else {
element.onValidate.apply(element.domNode, [FpJsFormValidator.getAllErrors(element, {}), event]);
if (element.isValid()) {
//item.submit();
}
}
});
};
this.get = function () {
var elements = [];
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
elements.push(item.jsFormValidator);
});
return elements;
};
//noinspection JSUnusedGlobalSymbols
this.addPrototype = function(name) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
var prototype = FpJsFormValidator.preparePrototype(
FpJsFormValidator.cloneObject(item.jsFormValidator.prototype),
name,
item.jsFormValidator.id + '_' + name
);
item.jsFormValidator.children[name] = FpJsFormValidator.createElement(prototype);
item.jsFormValidator.children[name].parent = item.jsFormValidator;
});
};
//noinspection JSUnusedGlobalSymbols
this.delPrototype = function(name) {
//noinspection JSCheckFunctionSignatures
FpJsFormValidator.each(this, function (item) {
delete (item.jsFormValidator.children[name]);
});
};
}
</script>
Second of all, if you're looking to override some stuff in the function:
<script type="text/javascript">
(function(){
// Store a reference to the original method.
var originalMethod = jQuery.fn.FpJsFormValidator;
// Define overriding method.
jQuery.fn.FpJsFormValidator = function(){
// Execute the original method.
originalMethod.apply( this, arguments );
}
})();
</script>
Note:
You need to write this code after loading the original function.
I hope that somebody can help me.
I want to redeclare js function by extension.
For example, there is the basic js function on website:
function foo(){
..something here..
}
i want to redeclare it by own function with the same name. how it will be easiest to do?
edit 1. i'll try to explain better.
there is a native code in website:
Notifier = {
debug: false,
init: function (options) {
curNotifier = extend({
q_events: [],
q_shown: [],
q_closed: [],
q_max: 3,
q_idle_max: 5,
done_events: {},
addQueues: curNotifier.addQueues || {},
recvClbks: curNotifier.recvClbks || {},
error_timeout: 1,
sound: new Sound('mp3/bb1'),
sound_im: new Sound('mp3/bb2')
}, options);
if (!this.initFrameTransport() && !this.initFlashTransport(options)) {
return false;
}
this.initIdleMan();
if (!(curNotifier.cont = ge('notifiers_wrap'))) {
bodyNode.insertBefore(curNotifier.cont = ce('div', {id: 'notifiers_wrap', className: 'fixed'}), ge('page_wrap'));
}
},
destroy: function () {
Notifier.hideAllEvents();
curNotifier.idle_manager.stop();
curNotifier = {};
re('notifiers_wrap');
re('queue_transport_wrap');
},
reinit: function () {
ajax.post('notifier.php?act=a_get_params', {}, {
onDone: function (options) {
if (options) {
curNotifier.error_timeout = 1;
this.init(options);
} else {
curNotifier.error_timeout = curNotifier.error_timeout || 1;
setTimeout(this.reinit.bind(this), curNotifier.error_timeout * 1000);
if (curNotifier.error_timeout < 256) {
curNotifier.error_timeout *= 2;
}
}
}.bind(this),
onFail: function () {
curNotifier.error_timeout = curNotifier.error_timeout || 1;
setTimeout(this.reinit.bind(this), curNotifier.error_timeout * 1000);
if (curNotifier.error_timeout < 256) {
curNotifier.error_timeout *= 2;
}
return true;
}.bind(this)
});
}
}
and function Sound
function Sound(filename) {
var audioObjSupport = false, audioTagSupport = false, self = this, ext;
if (!filename) throw 'Undefined filename';
try {
var audioObj = ce('audio');
audioObjSupport = !!(audioObj.canPlayType);
if (('no' != audioObj.canPlayType('audio/mpeg')) && ('' != audioObj.canPlayType('audio/mpeg')))
ext = '.mp3?1';
else if (('no' != audioObj.canPlayType('audio/ogg; codecs="vorbis"')) && ('' != audioObj.canPlayType('audio/ogg; codecs="vorbis"')))
ext = '.ogg?1';
else
audioObjSupport = false;
} catch (e) {}
// audioObjSupport = false;
if (audioObjSupport) {
audioObj.src = filename + ext;
var ended = false;
audioObj.addEventListener('ended', function(){ended = true;}, true);
audioObj.load();
this.playSound = function() {
if (ended) {
audioObj.load();
}
audioObj.play();
ended = false;
};
this.pauseSound = function() {
audioObj.pause();
};
} else {
cur.__sound_guid = cur.__sound_guid || 0;
var wrap = ge('flash_sounds_wrap') || utilsNode.appendChild(ce('span', {id: 'flash_sounds_wrap'})),
guid = 'flash_sound_' + (cur.__sound_guid++);
var opts = {
url: '/swf/audio_lite.swf?4',
id: guid
}
var params = {
swliveconnect: 'true',
allowscriptaccess: 'always',
wmode: 'opaque'
}
if (renderFlash(wrap, opts, params, {})) {
var swfObj = browser.msie ? window[guid] : document[guid],
inited = false,
checkLoadInt = setInterval(function () {
if (swfObj && swfObj.paused) {
try {
swfObj.setVolume(1);
swfObj.loadAudio(filename + ext);
swfObj.pauseAudio();
} catch (e) {debugLog(e);}
}
inited = true;
clearInterval(checkLoadInt);
}, 300);
self.playSound = function() {
if (!inited) return;
swfObj.playAudio(0);
};
self.pauseSound = function() {
if (!inited) return;
swfObj.pauseAudio();
};
}
}
}
Sound.prototype = {
play: function() {
try {this.playSound();} catch(e){}
},
pause: function() {
try {this.pauseSound();} catch(e){}
}
};
when i try to add injection with redeclaration function Sound it doesn't work.
if i create my own function, for example, xSound and сall it this way:
cur.sound = new xSound('mp3/bb1');
it's working.
You can do it like this, for example:
foo = function(args) {
// method body...
}
JavaScript is a programming language where functions are first-class citizens so you can manipulate them like other types.
UPDATE:
Make sure that this piece of code actually does the redefinition and not the first definition. (thanks to #jmort253)
function foo(){
// ..something else here..
}
Remember that an extension's Content Script code and the webpage code run in different execution contexts.
So if you want to redefine a function that exists in the webpage context, you'll have to inject your code into the webpage. Take a look at this answer by Rob W for different methods of doing that:
Insert code into the page context using a content script
I got a simple plugin as below:
$.fn.ajaxSubmit = function(options){
var submisable = true;
}
I want to able to change/access the variable myvar from outside the plugin, by doing something like below:
$(function(){
$('form').ajaxSubmit();
$('div').click(function(){
submisable =false;
});
});
You can also create methods to access the variables that are inside a plug in:
$.fn.ajaxSubmit = function(options){
var submisable = true;
$.fn.ajaxSubmit.setSubmissable = function(val){
submisable = val;
}
}
Then you can call it like this.
$('form').ajaxSubmit();
$('form').ajaxSubmit.setSubmissable(false);
This solution is not straight forward, but follows the jquery plugin guidelines.
(function($) {
var myVar = "Hi";
var methods = {
init: function(option) {
return this.each(function() {
$(this).data("test", myVar);
});
},
showMessage: function() {
return this.each(function() {
alert($(this).data("test"));
});
},
setVar: function(msg) {
return this.each(function() {
$(this).data("test", msg);
});
},
doSomething: function() {
//perform your action here
}
}
$.fn.Test = function(method) {
// Method calling logic
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.Test');
}
};
})(jQuery);
$("form").Test("init");
$("#getCol").click(function() {
$("form").Test("setVar", "Hello World").Test("showMessage");
});
Are you thinking to access them as properties? Something like:
$.fn.ajaxSubmit = function(options) {
var defaults = {},
o = $.extend({}, defaults, options);
var _myvar = 'blue'
this.myvar = new function(){
return _myvar;
}
this.setmyvar = function(_input){
_myvar = _input
}
return this.each(function() {
if (_myvar == 'blue') {
alert('hi');
}
if (_myvar == 'red') {
alert('bye');
}
});
}
And set like:
this.setmyvar('red');