Overriding a Method in Javascript - javascript

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.

Related

Referencing Settings Object from Init function in jquery

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>

using Javascript within Google Analytics event tracking code to automate category naming

So I'm attempting to implement some google analytics event tracking on dynamically generated pages. I'll be using something like
<script>
$(document).ready(function(){
$("#button1").click(function(){
_gaq.push(['_trackEvent', category, action, opt_label, opt_value, opt_noninteraction)']);
});
$("#button2").click(function(){
_gaq.push(['_trackEvent', category, action, opt_label, opt_value, opt_noninteraction']);
});
});
</script>
I'm wondering is it possible to use something like document.title to auto generate the category section of the GA code from the html title of the pages? All the pages use unique titles and it would be great if the events tracked on those pages could show up in GA as separate entries and not just category.
That was tougher than I expected it. Hope it helps.
Live demo with examples
javascript
// Unbind default behaviour
$(document).off("ready.ga").on("ready", function () {
//hollow out
pageLoc = $(location).attr('href');
// Introduce helper functions.
(function ($, window, undef) {
// ga selector.
$.extend($.expr[":"], {
ga: function (a) {
var attr = a.attributes,
len = attr.length;
while (len--) {
if (attr[len].name.indexOf("data-ga-") !== -1) {
return true;
}
}
return false;
}
});
$.gaaApi = {
trackEvent: {
event: {
value: "_trackEvent",
validation: "isString",
type: "string"
},
category: {
value: null,
validation: "optString",
type: "currentloc"
},
action: {
value: null,
validation: "optString",
type: "string"
},
label: {
value: null,
validation: "optString",
type: "string"
},
value: {
value: null,
validation: "optInt",
type: "integer"
},
nonInteraction: {
value: null,
validation: "optBool",
type: "boolean"
}
},
trackPageview: {
event: {
value: ["trackPageview", $(location).attr('href')],
validation: "isString",
type: "string"
},
url: {
value: undef,
validation: "optString",
type: "string"
}
}
};
var validation = {
isString: function (obj) {
var empty = true;
if (obj && typeof obj === "string") {
empty = /^\s*$/.test(obj);
}
// If empty === true then something is wrong and we should return false.
return !(empty);
},
optString: function (obj) {
if (obj === undef) {
return true;
}
return validation.isString(obj);
},
isInt: function (obj) {
return (/^[\-+]?\d+$/).test(obj) || (obj === +obj && obj === (obj | 0));
},
optInt: function (obj) {
if (obj === undef) {
return true;
}
return validation.isInt(obj);
},
isFloat: function (obj) {
return (/^[\-+]?\d+(\.\d+)?$/).test(obj) || (obj === +obj && obj !== (obj | 0));
},
optFloat: function (obj) {
if (obj === undef) {
return true;
}
return validation.isFloat(obj);
},
isBool: function (obj) {
return (obj === true || obj === "true") || (obj === false || obj === "false");
},
optBool: function (obj) {
if (obj === undef) {
return true;
}
return validation.isBool(obj);
}
},
methods = {
validate: function (param, name, location) {
var $element = this.$element,
data = $element.data("ga-" + name.toLowerCase()),
isValid;
//pageLoc = $(location).attr('href');
if (!validation[param.validation]) {
throw new TypeError("Unknown validation type");
}
// Check the value.
isValid = validation[param.validation](data);
if (!isValid) {
throw new Error("object validation error on " + name);
}
// Assign the value.
// Some analytics methods accept numbers as strings so we check the return type.
switch (param.type) {
case "integer":
return data ? parseInt(data, 10) : null;
case "float":
return data ? parseFloat(data) : null;
case "boolean":
return data ? Boolean(data) : null;
case "currentloc":
return data;
default:
// Default to string.
return data ? data + "" : null;
}
},
createArgs: function () {
var binder = this,
event = this.event,
args = $.map(event, function (val, key, pageLoc) {
var pageLoc = $(location).attr('href');
var value;
if (key === "event") {
// We don't want to check for the event property in the DOM.
value = val.value;
} else {
// Validate and return the correct value from the DOM.
value = methods.validate.call(binder, val, key, pageLoc);
}
return value;
});
return args;
}
},
gaa = function (element, options) {
this.$element = $(element);
this.options = $.extend({}, $.fn.gaa.defaults, options);
};
gaa.prototype = {
constructor: gaa,
trackEvent: function () {
var trackedEvent = $.Event("tracked.ga");
var currentLoc = $(location).attr('href');
this.args = methods.createArgs.call(this);
if (this.options.logit) {
if (window.console && window.console.log) {
// Push the data.
console.log("pushing to Google analytics", this.args);
this.$element.trigger(trackedEvent).trigger(currentLoc);
// this.$element.trigger(currentLocation);
}
} else {
var gaq = window._gaq;
if (gaq) {
// Set the context for our deferred callback.
var binder = this;
// Push the data.
$.when(gaq.push(args)).done(
function () {
this.$element.trigger(trackedEvent);
// this.$element.trigger(trackedEvent);
// Redirect the location - delayed so that any other page functionality has time to run.
setTimeout(function () {
var href = binder.attr("href");
if (href && href.indexOf("#") !== 0) {
window.location = href;
}
}, 100);
});
} else {
throw new ReferenceError(" _gaq not there");
}
}
}
};
// wrapper definition
$.fn.gaa = function (options) {
return this.each(function () {
var $this = $(this),
data = $this.data("ga"),
opts = typeof options === "object" ? options : null;
if (!data) {
// Check the data and assign if not present.
$this.data("ga", (data = new gaa(this, opts)));
}
// Run the appropriate function is a string is passed.
if (typeof options === "string") {
data[options]();
} else {
var handler = data.options.handler.toLowerCase(),
// Check for the event attr here as it might be other than the default.
event = data.$element.attr("data-ga-event");
// Overwrite if necessary.
$.extend(data.options, {
event: event
});
// Build the data as we have nothing there.
// First assign the event.
data.event = $.gaaApi[data.options.event];
// Then bind the handler.
if (handler === "load") {
data.trackEvent();
} else {
data.$element.on(handler + ".ga", function (e) {
e.preventDefault();
data.trackEvent();
});
}
}
});
};
// Define the defaults.
$.fn.gaa.defaults = {
event: ["trackEvent", "giveLocation"],
handler: "load",
logit: false
};
// Set the public constructor.
$.fn.gaa.Constructor = gaa;
// Let's BEGIN
$(document).on("ready.ga", function () {
// Bind using the custom selector.
$(":ga").each(function () {
$(this).gaa();
});
});
}(jQuery, window));
// Set some options the ones below are the defaults.
var options = {
event: "trackEvent", // The event name unprefixed.
handler: "click", // The eventhandler to trigger the tracking.
// Using 'load' will track immediately.
logit: true, //to logit
};
var options2 = {
event: "trackPageview", // The event name unprefixed.
handler: "click", // The eventhandler to trigger the tracking.
// Using 'load' will track immediately.
logit: true, //to logit
};
var options3 = {
event: "trackPageview", // The event name unprefixed.
handler: "load", // The eventhandler to trigger the tracking.
// Using 'load' will track immediately.
logit: true //to logit
};
// Binds using the custom selector.
$("load.trigger").gaa(options3); //fires a ga onload after domready
$("button.button1").gaa(options2).click(function () {
console.log('\nmore button events\n', 'heres the URL:', location.href)
});
$("#clickme").gaa(options).click(function () {
$(this).toggleClass("changeIt");
});
});
index.html
<load class="trigger">loading triggers ga event</load>
<button class="button1">fire ga event with address</button>
<button class="button1" id="clickme">multiple events</button>
The location bind happens here and lets jquery consume location properly.
event: {
value: ["trackPageview",$(location).attr('href')],
validation: "isString",
type: "string"
}
your approach of using this was correct but you had to get the location earlier to get it into ga. It seems like anyways this format
$("#button").gaa(options).click(function () {
$(this).toggleClass("changeIt");
});
Will get you going in the right directions.
This was a fun brainache. That should give you access to location.href where you want need it later on. The idea is to form a bind after DOM ready but before _gaq execution.

redeclare javascript 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

JavaScript singleton patterns - differences?

This may seem like a silly question, but what are the functional differences, if any, between these two patterns? Is there no real functional difference and it's just a matter of organization preference? What are some instances when you would want to use one and not the other? I'm trying to find a design pattern I feel most comfortable with. Thanks!
$(function(){
Core.init();
});
var Core = {
init: function() {
//some initialization code here
}
_plugins: function() {
//instantiate some plugins here
}
_display: function() {
//some more code here
}
_otherfunctions: function() {
....
}
}
and
$(function(){
Core.init();
Plugins.init();
Display.init();
});
var Core = {
init: function() {
//some initialization code here
}
}
var Plugins = {
init: function() {
//start plugins
}
_modify: function() {
//more code
}
}
var Display = {
init: function() {
//some init code
}
}
The main organizational difference is that the first pattern pollutes the global namespace less.
If you do want to separate your code into packages like in the second example, then the better way, within your example, would be:
$(function(){
Core.init();
});
var Core = {
init: function() {
//some initialization code here
},
plugins: {
init: function() {
//start plugins
}
_modify: function() {
//more code
}
},
display: {
init: function() {
//some init code
}
}
}
and refer to the packages through your main namespace:
Core.plugins.init();
I am not saying that this is the best way to do so in general (some of it is a matter of preference, like private members and methods), but in your example - I'd prefer mine.
Have a look at this framework I have built. Seems to work pretty well.
var gtg = gtg || {};
(function () {
var _this = this;
this.registerNamespace = function (namespace) {
var root = window,
parts = namespace.split("."),
i;
for (i = 0; i < parts.length; i++) {
if (typeof root[parts[i]] === "undefined") {
root[parts[i]] = {};
}
root = root[parts[i]];
}
return this;
};
}).call(gtg);
// Register Namespaces
gtg.registerNamespace("gtg.core");
gtg.registerNamespace("gtg.infoBar");
gtg.registerNamespace("gtg.navBar");
gtg.registerNamespace("gtg.tabBar");
gtg.registerNamespace("gtg.utils");
(function () {
var _this = this;
this.initialize = function () { };
}).call(gtg.core);
(function () {
var _this = this,
$container,
$messageContainer,
$message;
function configureMessage(message) {
var className = "info",
types = ["error", "info", "warning"];
for (var i in types) {
$message.removeClass(types[i]);
}
switch (message.MessageType) {
case 0:
className = "error"
break;
case 1:
className = "info"
break;
case 2:
className = "warning"
break;
}
$message.addClass(className).html(message.Message);
}
this.initialize = function () {
$container = $(".info-bar-container");
$messageContainer = $container.find(".message-container");
$message = $messageContainer.find(".message");
$messageContainer.find(".close a").bind("click", function () {
_this.close();
});
};
this.close = function () {
$messageContainer.fadeOut(300, function () {
$container.slideUp(300);
});
};
this.show = function (message) {
if ($container.css("display") !== "none") {
$messageContainer.fadeOut(300, function () {
configureMessage(message);
$messageContainer.fadeIn(300);
});
} else {
$container.slideDown(300, function () {
configureMessage(message);
$messageContainer.fadeIn(300);
});
}
};
}).call(gtg.infoBar);
(function () {
var _this = this;
function initializeNavBar() {
var paths = window.location.pathname.split("/"),
navId;
$("#nav-bar ul.top-nav li a[data-nav]").bind("click", function () {
_this.switchNav($(this));
});
if (paths[1] != "") {
switch (paths[1]) {
case "Customer":
navId = "customers-nav";
break;
case "Order":
navId = "orders-nav";
break;
case "Product":
navId = "products-nav";
break;
case "Report":
navId = "reports-nav";
break;
case "Tool":
navId = "tools-nav";
break;
}
if (navId != "") {
_this.switchNav($('#nav-bar ul.top-nav li a[data-nav="' + navId + '"]'));
}
} else {
_this.switchNav($('#nav-bar ul.top-nav li a[data-nav="home-nav"]'));
}
}
this.initialize = function () {
initializeNavBar();
};
this.switchNav = function (navItem) {
$("#nav-bar ul.top-nav li a[data-nav]").each(function (i) {
$(this).removeClass("selected");
$("#" + $(this).data("nav")).hide();
});
navItem.addClass("selected");
$("#" + navItem.data("nav")).show();
};
}).call(gtg.navBar);
(function () {
var _this = this;
this.initialize = function () {
$(".tab-bar ul li a[data-tab-panel]").bind("click", function () {
_this.switchTab($(this));
});
};
this.switchTab = function (tab) {
$(".tab-bar ul li a[data-tab-panel]").each(function (i) {
$(this).removeClass("selected");
$("#" + $(this).data("tab-panel")).hide();
});
tab.addClass("selected");
$("#" + tab.data("tab-panel")).show();
};
}).call(gtg.tabBar);
(function () {
var _this = this;
this.focusField = function (fieldId) {
$("#" + fieldId).select().focus();
};
this.loadJQTemplate = function (templateName, callback) {
$.get("/Content/JQTemplates/" + templateName + ".html", function (template) {
callback(template);
});
};
}).call(gtg.utils);
$(document).ready(function () {
gtg.core.initialize();
gtg.infoBar.initialize();
gtg.navBar.initialize();
gtg.tabBar.initialize();
});

Jquery - Access variable from outside the plugin

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');

Categories