I create a free jQuery plugin and what I would like to do is to create some add-ons that will be able for my clients under payment.
So, let's suppose that the free jQuery plugin that I offer for free append hello world into an html div tag and I would like to create an add-on that makes the div background color red.
Free Version of plugin:
(function(window, $) {
var example = function(elem, options) {
this.elem = elem;
this.$elem = $(elem);
this.options = options;
this.metadata = this.$elem.data('example-options');
};
example.prototype = {
defaults: {
message: 'Hello world!'
},
init: function() {
this.config = $.extend({}, this.defaults, this.options, this.metadata);
this.displayMessage();
return this;
},
displayMessage: function() {
this.$elem.append('<h1>'+this.config.message+'</h1>');
}
}
example.defaults = example.prototype.defaults;
$.fn.example = function(options) {
return this.each(function() {
new example(this, options).init();
});
};
window.example = example;
})(window, jQuery);
And I would like to create an addon that will be in a different js file, like this:
example.prototype = {
bgColor: function() {
this.$elem.css('background-color', '#f00');
}
};
How can I do this?
Rather than replacing the default prototype that you have created, simply add to it and override methods that you wish to change. For example, you can add your bgColor method to the prototype as follows:
example.prototype.bgColor = function() {
this.$elem.css('background-color', '#f00');
};
To override methods to provide enhanced functionality, you can do the same:
example.prototype.displayMessage = function() {
this.$elem.append('<h1>This message comes from the add-on</h1>');
}
Note that for this to work, the add-on js file is included after the default plugin js file.
Related
I'm trying to Create Snippets in odoo 10 according to https://www.odoo.com/documentation/10.0/howtos/themes.html#create-snippets
I created the snippets and add the js option, the code from the example
(function() {
'use strict';
var website = odoo.website;
website.odoo_website = {};
website.snippet.options.snippet_testimonial_options = website.snippet.Option.extend({
on_focus: function() {
alert("On focus!");
}
})
})();
fails since odoo.website is not defined see
Please help
here is the correct code for /theme_tst/static/src/js/tutorial_editor.js
odoo.define('snippet_testimonial_options', function(require) {
'use strict';
var options = require('web_editor.snippets.options');
options.registry.snippet_testimonial_options = options.Class.extend({
on_focus: function() {
alert("On focus!")
},
});
});
for odoo11: I need to change on_focus to onFocus (didn't try on odoo10)
odoo.define('snippet_testimonial_options', function(require) {
'use strict';
var options = require('web_editor.snippets.options');
options.registry.snippet_testimonial_options = options.Class.extend({
onFocus: function() {
alert("On focus!")
},
});
});
sombatsombat answer works for me. In odoo 12 onFocus is used. List of events are given on this link.
Also first argument snippet_testimonial_options is optional. we can simply ignore it.
odoo.define(function (require) {
var options = require('web_editor.snippets.options');
console.log(options);
options.registry.snippet_testimonial_options = options.Class.extend({
onFocus: function () {
alert("On focus!")
},
});
});
Searched for a similar question but cannot find anything as yet.
I have a RadEditor set up and I would like to override the event after the MediaManager file upload finishes so I can get the file and process it as i like. The FileBrowser I am using already has a 'prototype' but this is not leading me anywhere. I'm thinking it will be a JQuery/Javascript calls but I can't seem to find anything on the Telerik website.
Telerik.Web.UI.Editor.DialogControls.FileBrowser.prototype = {
initialize: function () {
this.set_insertButton($get("InsertButton"));
this.set_cancelButton($get("CancelButton"));
var previewer = this.get_previewerType();
var previewerType = eval("Telerik.Web.UI.Widgets." + previewer);
$create(previewerType, { "browser": this }, null, null, $get(previewer));
this.set_filePreviewer($find(previewer));
this.set_fileBrowser($find("RadFileExplorer1"));
Telerik.Web.UI.Editor.DialogControls.FileBrowser.callBaseMethod(this, 'initialize');
},
dispose: function () {
Telerik.Web.UI.Editor.DialogControls.FileBrowser.callBaseMethod(this, 'dispose');
this._insertButton = null;
this._cancelButton = null;
}
}
Fine the solution through http://demos.telerik.com/aspnet-ajax/editor/examples/onclientpastehtml/defaultcs.aspx
On the OnClientPasteHtml i do the following:
function OnClientPasteHtml(sender, args) {
var commandName = args.get_commandName();
var value = args.get_value();
if (commandName == "FlashManager") {
var object = document.createElement("object");
Telerik.Web.UI.Editor.Utils.setElementInnerHtml(object, value);
var movieObject = object.firstChild;
//object.firstChild.Movie //this is the url of the file just uploaded
args.set_value('Write custom html here');
}
else if (commandName == "MediaManager") {
}
}
I'm using Bootstrap Typeahead to suggest som search results. The results are returned from a ajax ressource, and since this resource creates a delay, I'm experiencing a unfortunate effect.
Example:
If typing a 4 letter word, the suggestions will appear after 2 letters, I can then go through the results with the keys up/down, but suddenly the suggestions will reload because the last request has finished.
Is there any way to "cancel" any remaining, if user is currently using the keys up/down to go through the suggestions?
('#query').typeahead({
items: 4,
source: function (query,process) {
map = {};
$.getJSON('/app_dev.php/ajax/autosuggest/'+query, function (data) {
vehicles = [];
$.each(data, function(i,vehicle){
map[vehicle.full] = vehicle;
vehicles.push(vehicle.full);
});
process(vehicles);
});
},
updater: function (item) {
// do something here when item is selected
},
highlighter: function (item) {
return item;
},
matcher: function (item) {
return true;
}
});
I think the following will satisfy your needs (its hard to reproduce exactly) :
There is no easy way to abort a delayed response, but you could extend typeahead as I figured out here (without modifying bootstrap.js)
The concept is to catch keydown, detect if the event is KEY_UP or KEY_DOWN, set a flag is_browsing, and then abort process if is_browsing is true (that is, if the user has hitted KEY_UP or KEY_DOWN and no other keys afterwards).
Extending typeahead :
// save the original function object
var _superTypeahead = $.fn.typeahead;
// add is_browsing as a new flag
$.extend( _superTypeahead.defaults, {
is_browsing: false
});
// create a new constructor
var Typeahead = function(element, options) {
_superTypeahead.Constructor.apply( this, arguments )
}
// extend prototype and add a _super function
Typeahead.prototype = $.extend({}, _superTypeahead.Constructor.prototype, {
constructor: Typeahead
, _super: function() {
var args = $.makeArray(arguments)
// call bootstrap core
_superTypeahead.Constructor.prototype[args.shift()].apply(this, args)
}
//override typeahead original keydown
, keydown: function (e) {
this._super('keydown', e)
this.options.is_browsing = ($.inArray(e.keyCode, [40,38])>-1)
}
//override process, abort if user is browsing
, process: function (items) {
if (this.options.is_browsing) return
this._super('process', items)
}
});
// override the old initialization with the new constructor
$.fn.typeahead = $.extend(function(option) {
var args = $.makeArray(arguments),
option = args.shift()
// this is executed everytime element.modal() is called
return this.each(function() {
var $this = $(this)
var data = $this.data('typeahead'),
options = $.extend({}, _superTypeahead.defaults, $this.data(), typeof option == 'object' && option)
if (!data) {
$this.data('typeahead', (data = new Typeahead(this, options)))
}
if (typeof option == 'string') {
data[option].apply( data, args )
}
});
}, $.fn.typeahead);
This typeahead-extension could be placed anywhere, eg in a <script type="text/javascript"> -section
Testing the extension :
<input type="text" id="test" name="test" placeholder="type some text" data-provide="typeahead">
<script type="text/javascript">
$(document).ready(function() {
var url='typeahead.php';
$("#test").typeahead({
items : 10,
source: function (query, process) {
return $.get(url, { query: query }, function (data) {
return process(data.options);
});
}
});
});
</script>
A "serverside" PHP script that returns a lot of randomized options with forced delay, typeahead.php :
<?
header('Content-type: application/json');
$JSON='';
sleep(3); //delay execution in 3 secs
for ($count=0;$count<30000;$count++) {
if ($JSON!='') $JSON.=',';
//create random strings
$s=str_shuffle("abcdefghijklmnopq");
$JSON.='"'.$s.'"';
}
$JSON='{ "options": ['.$JSON.'] }';
echo $JSON;
?>
It really seems to work for me. But I cannot be sure that it will work in your case. Let me now if you have success or not.
ok so im having a hard time hiding some layout sections (divs in my layout page and im using mvc3).
I have this js fragment which is basically the main logic:
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
});
//Cookies Functions========================================================
//Cookie for showing the right container
if ($.cookie('right_container_visible') === 'false') {
if ($('#RightContainer:visible')) {
$('#RightContainer').hide();
}
$.cookie('right_container_visible', null);
} else {
if ($('#RightContainer:hidden')) {
$('#RightContainer').show();
}
}
as you can see, im hidding the container whenever i click into some links that have a specific css. This seems to work fine for simple tests. But when i start testing it like
.contentExpand click --> detail button click --> .contentExpand click --> [here unexpected issue: the line $.cookie('right_container_visible', null); is read but it doesnt set the vaule to null as if its ignoring it]
Im trying to understand whats the right logic to implement this. Anyone knows how i can solve this?
The simpliest solution is to create variable outside delegate of bind.
For example:
var rightContVisibility = $.cookie('right_container_visible');
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
rightContVisibility = "false";
});
if (rightContVisibility === 'false') {
...
}
The best thing that worked for me was to create an event that can catch the resize of an element. I got this from another post but I dont remember which one. Anyway here is the code for the event:
//Event to catch rezising============================================================================
(function () {
var interval;
jQuery.event.special.contentchange = {
setup: function () {
var self = this,
$this = $(this),
$originalContent = $this.text();
interval = setInterval(function () {
if ($originalContent != $this.text()) {
$originalContent = $this.text();
jQuery.event.handle.call(self, { type: 'contentchange' });
}
}, 100);
},
teardown: function () {
clearInterval(interval);
}
};
})();
//=========================================================================================
//Function to resize the right container============================================================
(function ($) {
$.fn.fixRightContainer = function () {
this.each(function () {
var width = $(this).width();
var parentWidth = $(this).offsetParent().width();
var percent = Math.round(100 * width / parentWidth);
if (percent > 62) {
$('#RightContainer').remove();
}
});
};
})(jQuery);
//===================================================================================================
Here is my plugin
(function($){
$.fn.myPlugin = function(options){
var defaults = {
width: 800
};
var defaults = $.extend(defaults, options);
var self = this;
function init(obj){
/*Initialize object*/
self.myPlugin.doAnimation(600,400);
}
$.fn.myPlugin.doAnimation = function(lV, rV){
/*Doing some animation work*/
}
return this.each(function(options){
init(this);
});
}
})(jQuery);
I am trying like this
var t = $('#id1').myPlugin();
t.doAnimation(); //getting error here, t.doAnimation is not a function
You can't. You're not returning the plugin. You're returning the jQuery object with the matched element(s) (like you probably should). The testing function is private to the myPlugin function anyway.
To call a method against a jQuery object, you would need to extend jQuery like you did for your myPlugin(), as in:
function($){
$.fn.myPlugin = function(options) {
...
}
$.fn.testing = function(options) {
...
}
})(jQuery);
Of course this would be completely separate from the original plugin.
I don't know what your plugin does, but if you need to share some data between plugins on a per-element basis, you could probably use jQuery's .data() method.