How to prevent name mangling of javascript functions in django-pipeline - javascript

I am using django version 1.82 with django-pipeline. I call a particular javascript function from html by name.
<form class="navbar-form navbar-right vcenter"
action="javascript:search();" role="search" id='searchform'>
Unfortunately in the compressed js file, the name of the function is changed and hence the frontend functionality is not workig. How do I maintain the same name for that function or how do I change the reference to the js function in html?
I have installed yuglify and the settings I use is
PIPELINE_CSS = {
'allstyles': {
'source_filenames': (
'css/application.css',
'feedback/css/feedback-form.css',
),
'output_filename': 'css/nifty.css',
'extra_context': {
'media': 'screen,projection',
},
},
}
PIPELINE_JS = {
'actions': {
'source_filenames': (
'js/nifty.js',
'feedback/js/feedback-form.js',
),
'output_filename': 'js/nifty.js',
}
}
STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
PIPELINE_JS_COMPRESSOR = 'pipeline.compressors.yuglify.YuglifyCompressor'
PIPELINE_DISABLE_WRAPPER = True
PIPELINE_ENABLED=True

Are you sure that search() is a global function? To make sure you can assign it to the window variable:
window.search = function() {
...
}

I'd do it the other way around.
<form ... action="/nojs.html" ... id='searchform'>
and then intercept the submit event on the form.
(function(){
var sf = document.getElementById('searchform');
sf.addEventListener('submit', function(ev){
ev.preventDefault();
// do here whatever "search()" needs to do
});
})();
That way you don't need to add anything into the window namespace, are independent of minified function names, and a browser with disabled JS gets a readable error page.

Related

Using jQuery to manipulate xml odoo elements

I've made some new modules in my Odoo and now when each form is loading I need to manipulate the created XML elements according to its required model and my arbitrary changes or refer to some specific function for its data validation (I know there are other ways for data validation but I'm curious if it's possible to be done with jquery functions).
I've tried to add an HTML file in the view folder and write a simple script, to begin with, but I'm not sure if it's the right place or even the right piece of code.
<script>
$(document).ready(function()
{
$("input").keyup(function(event){
console.log('t');
});
});
</script>
I would be glad if anyone could offer some useful answers to my question.
You can customize an existing form view using the js_class attribute, its value will be the name of an extended form view.
To bind a new event to an input, you can customize the form controller and extend the events mapping.
Example:
1) Extend the form view:
odoo.define("MODULE_NAME.custom_form", function (require) {
"use strict";
var FormController = require('web.FormController');
var FormView = require('web.FormView');
var viewRegistry = require('web.view_registry');
var CustomController = FormController.extend({
events: _.extend({}, FormController.prototype.events, {
'keyup input': '_onInputKeyup',
}),
_onInputKeyup(ev) {
console.log('t');
},
});
var CustomFormView = FormView.extend({
config: _.extend({}, FormView.prototype.config, {
Controller: CustomController,
}),
});
viewRegistry.add('custom_form', CustomFormView);
return {
CustomController: CustomController,
CustomFormView: CustomFormView,
};
});
2) Add it to the assets entry in the manifest file
'assets': {
'web.assets_backend': [
'MODULE_NAME/static/src/js/custom_form_view.js'
],
},
3) Set the js_class attribute on the form view tag
<form js_class="custom_form">
For back-office javascript, consider using the "Odoo built-in js library":
In your custom module "my_custom_module":
Create a new file /my_custom_module/static/src/js/my_customization.js:
odoo.define('my_custom_module.switch_to_gantt', function(require) {
"use strict";
var core = require('web.core');
var _t = core._t;
var AbstractController = require('web.AbstractController');
AbstractController.include({
/**
* Original : Intercepts the 'switch_view' event to add the controllerID into the data, and lets the event bubble up.
* Included : On switching from Kanban to Gantt view : Remove all the GroupBy Filters because it caused Error
*/
_onSwitchView: function (ev) {
console.log(ev.data.view_type);
//debugger;
/* only on the specific view : gantt: */
if(ev.data.view_type == 'gantt')
{
/* only on the specific model : event.event: */
if(ev.target.modelName == 'event.event')
$('.o_searchview .o_facet_remove').click();
}
this._super.apply(this, arguments);
},
});
});
And declare this asset in the __manifest__.py file:
'assets': {'web.assets_qweb': ['/my_custom_module/static/src/js/my_customization.js']}
if you want to use jquery or any js library you need to put them in this file under this path /your_app/static/src/js/test.js
and the file should be like this :
$(document).ready(function()
{
$("input").keyup(function(event){
console.log('t');
});
});
and you need to add the assets for this work like that :
'assets': {'web.assets_qweb': ['/your_app/static/src/js/test.js']} #path of the file
this for jquery not for building js model in odoo

how to create javascript library for self-written functions

** want to call common js for all validation for 20 jsp f**
function mAbcRefresher(refresh, refreshTime) {
//function code
}
function QWERTY(address){
//function code
}
function ASDF(address, value, refreshCallback){....
........
........
........`
I just copy these functions to a JS file and include the JS file in my html document. i need some standard way to write this type of validation code
Firstly created that common file eg. common.js. Add it to all your jsp pages. The standered way to write the code in js file
//common.js file
var common={
//function name
formvalidation : function(){
//eg.you want to get all required parts
var elements=$("input:visible, select:visible , textarea:visible");
$.each($(elements) function( index, element ){
//you can get do your code.
$(element).attr("attr");
});
}
//check condition and return false or true
}
above coders for write common functions.
now in jsp to call the function
Add this js file to head
then you can call the function in jsp
like:
$( document ).ready(function() {
//will return true or false
if(common.formvalidation()){
//submit or not
}
});
you can call another function inside this formvalidation() function
just you have assign a variable for this function
var common={
//function name
formvalidation : function(){
var date=this;
var result=date.formDate();
}
formDate : function(){
// do your code
}
}
You can look above code for the idea. definitely it will be helpful for you

Multiple Dropzone in a single page

I'm using Dropzone without creating a dropzone form. It works great for me in this way.
But in this case I can not create another instance of Dropzone in my page.
var myDropzone1 = new Dropzone(
document.body,
{
url : "upload1"...
.
.
. some parameters
};
var myDropzone2 = new Dropzone(
document.body,
{
url : "upload'"...
.
.
. some parameters
};
When I do this, I'm getting the error Dropzone already attached.
It's possible, but you can't bind a second dropdzone on the same element, as you did. 2 Dropzones on one element makes no sense. 2x document.body in your solution atm. Try this...
HTML:
<form action="/file-upload" class="dropzone" id="a-form-element"></form>
<form action="/file-upload" class="dropzone" id="an-other-form-element"></form>
JavaScript:
var myDropzoneTheFirst = new Dropzone(
//id of drop zone element 1
'#a-form-element', {
url : "uploadUrl/1"
}
);
var myDropzoneTheSecond = new Dropzone(
//id of drop zone element 2
'#an-other-form-element', {
url : "uploadUrl/2"
}
);
I want to add something here because I have experienced problems with multiple dropzones on the same page.
In your init code you must remember to include var if putting a reference otherwise it isn't dealing with this instance of the dropzone rather trying to access/relate to the others.
Simple javascript but makes a big difference.
init: function(){
var dzClosure = this;
$('#Btn').on('click',function(e) {
dzClosure.processQueue();
});
Note: I'm not using Ajax in order to upload the image on server. For Ajax, One can use url. Attaching the doc DropzoneDoc. It's works like action.( Something like that. Check my solution you can get some idea to do it in your case.
When I working we dropzone, I faced a similar issue working with the Meteor framework.
In the case of Meteor Framework, dropzone is initialized in the below code. This will look different to you, it's the way to initialize in the Meteor framework.
In your case, you can find similarities when using the dropzone library.
Params are added as
params='{name: "Image1"}'
{{> dropzone url=getDropZoneImageUploadURL id='candidate-identity-photo-proof'
init=initFunction params='{name: "Image1"}'
acceptedMimeTypes= 'image/jpeg,image/png,image/jpg' maxFiles=1
success=uploadSuccessHandler maxFilesize=2 dictDefaultMessage= "Photo
ID Proof Photo"
previewsContainer='#upload-photo-id-holder'
previewTemplate=previewTemplateString}}
when the file is getting uploaded check "this" context as mentioned below code. You can use the params value to distinguish the image.
var initFunction = function () {
this.on("addedfile", function () {
if (this.files[1] != null) {
this.removeFile(this.files[0]);
}
});
this.on("sending", function (file, xhr, formData) {
console.log(this); // Here you can get the value
formData.append("type", "image");
});
this.on("error", function (fileInfo, errorMessage) {
var message = "ERROR";
showNotification("error", { message: message }, {});
});
};

How to place a jQuery snippet into a global file

I have a JavaScript file here http://www.problemio.com/js/problemio.js and I am trying to place some jQuery code into it that looks like this:
$(document).ready(function()
{
queue = new Object;
queue.login = false;
var $dialog = $('#loginpopup')
.dialog({
autoOpen: false,
title: 'Login Dialog'
});
var $problemId = $('#theProblemId', '#loginpopup');
$("#newprofile").click(function ()
{
$("#login_div").hide();
$("#newprofileform").show();
});
// Called right away after someone clicks on the vote up link
$('.vote_up').click(function()
{
var problem_id = $(this).attr("data-problem_id");
queue.voteUp = $(this).attr('problem_id');
voteUp(problem_id);
//Return false to prevent page navigation
return false;
});
var voteUp = function(problem_id)
{
alert ("In vote up function, problem_id: " + problem_id );
queue.voteUp = problem_id;
var dataString = 'problem_id=' + problem_id + '&vote=+';
if ( queue.login = false)
{
// Call the ajax to try to log in...or the dialog box to log in. requireLogin()
}
else
{
// The person is actually logged in so lets have him vote
$.ajax({
type: "POST",
url: "/problems/vote.php",
dataType: "json",
data: dataString,
success: function(data)
{
alert ("vote success, data: " + data);
// Try to update the vote count on the page
//$('p').each(function()
//{
//on each paragraph in the page:
// $(this).find('span').each()
// {
//find each span within the paragraph being iterated over
// }
//}
},
error : function(data)
{
alert ("vote error");
errorMessage = data.responseText;
if ( errorMessage == "not_logged_in" )
{
//set the current problem id to the one within the dialog
$problemId.val(problem_id);
// Try to create the popup that asks user to log in.
$dialog.dialog('open');
alert ("after dialog was open");
// prevent the default action, e.g., following a link
return false;
}
else
{
alert ("not");
}
} // End of error case
}
}); // Closing AJAX call.
};
$('.vote_down').click(function()
{
alert("down");
problem_id = $(this).attr("data-problem_id");
var dataString = 'problem_id='+ problem_id + '&vote=-';
//Return false to prevent page navigation
return false;
});
$('#loginButton', '#loginpopup').click(function()
{
alert("in login button fnction");
$.ajax({
url:'url to do the login',
success:function() {
//now call cote up
voteUp($problemId.val());
}
});
});
});
</script>
There are two reasons why I am trying to do that:
1) I am guessing this is just good practice (hopefully it will be easier to keep track of my global variables, etc.
2) More importantly, I am trying to call the voteUp(someId) function in the original code from the problemio.js file, and I am getting an error that it is an undefined function, so I figured I'd have better luck calling that function if it was in a global scope. Am I correct in my approach?
So can I just copy/paste the code I placed into this question into the problemio.js file, or do I have to remove certain parts of it like the opening/closing tags? What about the document.ready() function? Should I just have one of those in the global file? Or should I have multiple of them and that won't hurt?
Thanks!!
1) I am guessing this is just good practice (hopefully it will be
easier to keep track of my global variables, etc.
Yes and no, you now have your 'global' variables in one spot but the chances that you're going to collide with 'Global' variables (ie those defined by the browser) have increased 100% :)
For example say you decided to have a variable called location, as soon as you give that variable a value the browser decides to fly off to another URL because location is a reserved word for redirecting.
The solution to this is to use namespacing, as described here
2) More importantly, I am trying to call the voteUp(someId) function
in the original code from the problemio.js file, and I am getting an
error that it is an undefined function, so I figured I'd have better
luck calling that function if it was in a global scope. Am I correct
in my approach?
Here's an example using namespacing that will call the voteUp function:
(function($) {
var myApp = {};
$('.vote_up').click(function(e) {
e.preventDefault();
myApp.voteUp();
});
myApp.voteUp = function() {
console.log("vote!");
}
})(jQuery);
What about the document.ready() function? Should I just have one of
those in the global file? Or should I have multiple of them and that
won't hurt?
You can have as many document.ready listeners as you need, you are not overriding document.ready you are listening for that event to fire and then defining what will happen. You could even have them in separate javascript files.
Be sure your page is finding the jquery file BEFORE this file is included in the page. If jquery is not there first you will get function not defined. Otherwise, you might have other things conflicting with your jquery, I would look into jquery noConflict.
var j = jQuery.noConflict();
as seen here:
http://api.jquery.com/jQuery.noConflict/
Happy haxin
_wryteowl
Extending what KreeK has already provided: there's no need to define your "myApp" within the document ready function. Without testing, I don't know off the top of my head if doing so is a potential source for scope issues. However, I CAN say that the pattern below will not have scope problems. If this doesn't work, the undefined is possibly a script-loading issue (loading in the right order, for example) rather than scope.
var myApp = myApp || {}; // just adds extra insurance, making sure "myApp" isn't taken
myApp.voteUp = function() {
console.log("vote!");
}
$(function() { // or whatever syntax you prefer for document ready
$('.vote_up').click(function(e) {
e.preventDefault();
myApp.voteUp();
});
});

How can I use jQuery and Javascript from firefox add-on?

I can't create a new element in the page. I check the page and domain when the page is onload, that's work, but I don't know how can I create a new element in the correct window page.
window.addEventListener("load", function() { myExtension.init(); }, false);
var myExtension = {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
},
onPageLoad: function(aEvent) {
var unsafeWin = aEvent.target.defaultView;
if (unsafeWin.wrappedJSObject) unsafeWin = unsafeWin.wrappedJSObject;
var locationis = new XPCNativeWrapper(unsafeWin, "location").location;
var hostis = locationis.host;
//alert(hostis);
if(hostis=='domain.com')
{
var pathnameis=locationis.pathname;
if(pathnameis=='/index.php')
{
$("#left .box:eq(0)").after('<div id="organic-tabs" class="box"></div>'); // this code somewhy doesn't working, but if I copy to FireBug it't work.
}
}
}
}
My question is: How can I use Javascript and jQuery from firefox addon when I want to manipulate html in the correct window content? What is need from here
$("#left .box:eq(0)").after('<div id="organic-tabs" class="box"></div>');
for working.
This code has a bunch of issues. For one, appcontent is not the browser, gBrowser is. So it should be:
init: function() {
gBrowser.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
},
Then, using wrappedJSObject is absolutely unnecessary (and also not safe the way you do it).
var wnd = aEvent.target.defaultView;
var locationis = wnd.location;
Finally, you are trying to select an element in the browser document (the document that your script is running in), not in the document loaded into the tab. You need to give jQuery an explicit context to work on:
$("#left .box:eq(0)", wnd.document)
But you shouldn't use jQuery like that, it defines a number of global variables that might conflict with other extensions. Instead you should call jQuery.noConflict() and create an alias for jQuery within myExtension:
var myExtension = {
$: jQuery.noConflict(true),
....
myExtension.$("#left .box:eq(0)", wnd.document)
Here is a template you can use that incorporates your sample code. I also added an additional statement so you could see another use of jQuery. Important points:
You must load jQuery before you can use it. You should myplace the jQuery library file you want to use in Chrome, for example, in the chrome/content directory.
Use window.content.document as the context for every jQuery
operation on the contents of the Web page
Use this as the context of a successful search result to help you
insert code in the correct spot.
window.addEventListener('load', myExtension.init, false);
var myExtension = {
jq : null,
init : function() {
var app;
// Load jQuery
var loader = Components.classes["#mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://myExtension/content/jquery-1.5.2.min.js");
myExtension.jq = jQuery.noConflict();
// Launch extension
if ((app = document.getElementById("appcontent"))) {
app.addEventListener("DOMContentLoaded", myExtension.run, true);
}
},
run : function() {
// make sure this is the correct Web page to change
var href = event.originalTarget.location.href;
if (href && href.match(/http:\/\/(www\.)?domain\.com\/(index\.php)/i)) {
changeScreen();
}
},
changeScreen : function() {
// make changes to the screen
// note the "window.content.document) in the first jQuery selection
myExtension.jq("#left .box:eq(0)", window.content.document).after('');
// note the use of "this" to use the search results as the context
myExtension.jq("#right", window.content.document).each(function() {
myExtension.jq("tr td", this).append('MATCH!');
});
}
}

Categories