An object disappears after packing a JavaScript library - javascript

I have created a JavaScript library and packed it with these options selected : Shrink Variables and Base62 Encoded at this url: http://dean.edwards.name/packer/. In this library I have declared an object ax, but when I use the packed version in my web page I get an error saying Uncaught ReferenceError: ax is not defined.
The original code of this library looks like below.
var ax = {
scaleUp:function(win) {
//code omitted
},
downGrade:function(win) {
//code omitted
}
}
In my web page in which I am using this library, I have code like below. This code works, if instead of packing, I minify it using Microsoft's Minifier or just use the original JavaScript library without minification or packing.
var result = ax.downGrade(w);
Question :
Why is the variable ax not accessible with packed version? Do I need to add something else when using the packed version?
UPDATE 1:
I could not get the packed file to work but packing my code through another compression utility at following url worked in my case: http://jsutility.pjoneil.net/. It provided an equally good compression.
I am still not sure why the utility at original url failed to produce a working version of my library, even though my original code works without any errors on any web page.

Check your console for errors before trying to call ax. Explicitly place semi-colons where they belong.Example at the end of the definition for ax you should put a semi-colon, even though in standard code it's good as is. Remove the explicit var declarations. When I did these things:
ax = {
scaleUp:function(win) {
alert("up");
},
downGrade:function(win) {
alert("down");
}
};
result = ax.downGrade();
Ran without issue in jsFiddle and console: http://jsfiddle.net/7kdnw65n/. I suspect it has to do with how the algorithm "shrinks" the variables. The resulting pack was:
eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0={5:1(2){3("6")},4:1(2){3("7")}};8=0.4();',9,9,'ax|function|a|alert|downGrade|scaleUp|up|down|result'.split('|'),0,{}))

Related

Clojurescript Extern for Nested Function

I am developing a Single Page Application in Clojurescript, and I want to use TinyMCE as a WYSIWYG editor for certain fields. For space efficiency, I want to eventually minify the project using the google clojure compiler in advanced mode. Since the tinymce dev javascript files seems to be unsuitable for use as an extern file, I'm forced to write my own.
There is one particular function call that I can't get to work. In clojurescript, I call:
(.setContent (.get js/tinymce id) cont)
which I'd imagine would compile to something like:
tinymce.get(id).setContent(cont);
I have tried many different function definitions in my externs, yet I keep getting an error:
TypeError: tinymce.get(...).Tl is not a function
Which tells me setContent gets obscured away by the compiler. My current extern file looks like this:
//all seems to be well here...
var tinymce;
tinymce.get = function(name){};
tinymce.remove = function(node){};
tinymce.init = function(editor){};
tinymce.on = function(name, callback, prepend, extra){};
//tinymce setContent attempts
var tinymce.Editor;
tinymce.Editor.prototype.setContent = function(content){};
tinymce.Editor.setContent = function(content){};
tinymce.get(name).setContent = function(content){};
tinymce.get(name).prototype.setContent = function(content){};
var Editor;
Editor.prototype.setContent = function(content){};
Editor.setContent = function(content){};
Which currently is kind of a throw-everything-against-the-wall-and-see-what-sticks attempt. The object get(name) returns should be in the namespace tinymce.Editor.
Is there a proper way of writing an externs to catch these chained function calls? Or is there a way to rewrite the first code snippet so my externs properly preserve the function names? Thanks in advanced.
This line:
var tinymce.Editor;
is not syntactically correct in JS:
SyntaxError: missing ; before statement
Remove it and leave this line:
tinymce.Editor.prototype.setContent = function(content){};
This should work fine.
Also you may always fall back to accessing properties via string literals which will never be renamed:
(require '[goog.object :as gobj])
(gobj/get your-object "i-wont-be-renamed")

Can you share code between multiple grafana scripted dashboards?

I have created a couple of scripted dashboards for Grafana. I'm about to create another. There are all kinds of utility functions that I created and copied from script to script. I would much rather employ good programming practice and import the code rather than copy-paste.
Can that be done? If so, how would one do it?
Yes, this can be done.
This link suggests that SystemJS.import() can be used, although I have not tried it.
This github repo provides a detailed example using a different technique.
Although its not mentioned in the slim Grafana scripted dashboard doc, some version of lodash.com (commit to include lodash) and jquery seem to be available to all scripted dashboards.
The owner of this repo, anryko, has figured out how to use these two libraries to reference your own utility scripts like you're talking about.
All scripted dashboards have a main script; getdash.sh is anryko's main script, as seen by the dash URL on the README.md:
http://grafanaIP/dashboard/script/getdash.js
If you look at the end of getdash.sh, you'll see this line that references code in other user(you)-provided scripts:
var dash = getDashApp(datasources, getDashConf());
For example:
the code for getDashConf() is in this separate .js file
the code for getDashApp() is in this other separate .js file.
Here is the part where getdash.js uses jquery and lodash to load the source files:
// loadScripts :: [scriptSourceStr] -> Promise([jQuery.getScript Result])
var loadScripts = function loadScripts (scriptSrcs) {
var gettingScripts = _.map(scriptSrcs, function (src) {
return $.getScript(src);
});
return Promise.all(gettingScripts);
};
Here is the lodash doc for the above _.map.
The function scriptedDashboard() (also in getdash.js) calls the above loadScripts(), passing it the paths to the source files like this:
loadScripts([
'public/app/getdash/getdash.app.js',
'public/app/getdash/getdash.conf.js'
]).then(function () {
To be honest, I haven't yet looked further under the covers to see how all this makes the utility code 'reference-able.'

Moving created files with JXA

I'm new to JXA scripting, but I'm attempting to troubleshoot some older scripts currently in place here at work. They loop through an InDesign document and create several PDFs based on it. Previously, they would be stored in a folder called "~/PDFExports". However, this doesn't work with 10.10.
If I change the code to just place the PDFs in "~/", it works fine. From there, I'd like to move the files to "~/PDFExports", but I can't seem to find an answer on how to do that. I've seen things about making calls to ObjC, or to call Application('Finder'), but neither work - they both return undefined.
Am I just missing something basic here, or is it really this hard to simply move a file with JXA?
EDIT: Some syntax for how I'm creating the folder in question and how I'm attempting to work with Finder.
//This is called in the Main function of the script, on first run.
var exportFolder = new Folder(exportPath);
if(!exportFolder.exists) {
exportFolder.create();
}
//This is called right after the PDF is created. file is a reference to the
actual PDF file, and destination is a file path string.
function MoveFile(file,destination){
var Finder = Application("Finder");
Application('Finder').move(sourceFile, { to: destinationFolder });
alert("File moved");
}
Adobe apps have long included their own embedded JS interpreter, JS API, and .jsx filename extension. It has nothing to do with JXA, and is not compatible with it.
InDesign's JSX documentation:
http://www.adobe.com/devnet/indesign/documentation.html#idscripting
(BTW, I'd also strongly advise against using JXA for Adobe app automation as it has a lot of missing/broken features and application compatibility problems, and really isn't fit for production work.)
Here's the link to Adobe's InDesign Scripting forum, which is the best place to get help with JSX:
https://forums.adobe.com/community/indesign/indesign_scripting
You could use Cocoa to create the folder
var exportFolder = $.NSHomeDirectory().stringByAppendingPathComponent("PDFExports")
var fileManager = $.NSFileManager.defaultManager
var folderExists = fileManager.fileExistsAtPath(exportFolder)
if (!folderExists) {
fileManager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(exportFolder, false, $(), $())
}
and to move a file
var success = fileManager.moveItemAtPathToPathError(sourceFile, destinationLocation, $());
if (success) alert("File moved");
Consider that destinationLocation must be the full path including the file name
and both sourceFile and destinationLocation must be NSString objects like exportFolder
Could it be that the folder is missing ? Could be your reference to the folder object not valid ? Any syntax to show ?
I will share some of what I learned about JXA move and duplicate methods. I am not a professional programmer just an attorney that is passionate about automation. My comments come from much trial and error, reading whatever I could find online, and A LOT of struggle. The move method does not work well with Finder. Use the System Events move method instead. The duplicate method in Finder works just fine. The duplicate method does not work well in system events. This is a modified snippet from a script I wrote showing move() using System Events.
(() => {
const strPathTargetFile = '/Users/bretfarve/Documents/MyFolderA/myFile.txt';
const strPathFolder = '/Users/bretfarve/Documents/MyFolderB/';
/* System Events Objects */
const SysEvents = Application('System Events');
const objPathFolder = SysEvents.aliases[strPathFolder];
SysEvents.move(SysEvents.aliases.byName(strPathTargetFile), {to: objPathFolder});
})();

IPython: Adding Javascript scripts to IPython notebook

As a part of a project, I need to embedd some javascripts inside an IPython module.
This is what I want to do:
from IPython.display import display,Javascript
Javascript('echo("sdfds");',lib='/home/student/Gl.js')
My Gl.js looks like this
function echo(a){
alert(a);
}
Is there some way so that I can embed "Gl.js" and other such external scripts inside the notebook, such that I dont have to include them as 'lib' argument everytime I try to execute some Javascript code which requires to that library.
As a very short-term solution, you can make use of the IPython display() and HTML() functions to inject some JavaScript into the page.
from IPython.display import display, HTML
js = "<script>alert('Hello World!');</script>"
display(HTML(js))
Although I do not recommend this over the official custom.js method, I do sometimes find it useful to quickly test something or to dynamically generate a small JavaScript snippet.
Embedding D3 in an IPython Notebook
https://blog.thedataincubator.com/2015/08/embedding-d3-in-an-ipython-notebook/
To summarize the code.
Import the script:
%%javascript
require.config({
paths: {
d3: '//cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.min'
}
});
Add an element like this:
%%javascript
element.append("<div id='chart1'></div>");
Or this:
from IPython.display import Javascript
#runs arbitrary javascript, client-side
Javascript("""
window.vizObj={};
""".format(df.to_json()))
IPython Notebook: Javascript/Python Bi-directional Communication
http://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/
A more extensive post explaining how to access Python variables in JavaScript and vice versa.
I've been fighting with this problem for several days now, here's something that looks like it works; buyer beware though, this is a minimal working solution and it's neither pretty nor optimal - a nicer solution would be very welcome!
First, in .ipython/<profile>/static/custom/myScript.js, we do some require.js magic:
define(function(){
var foo = function(){
console.log('bar');
}
return {
foo : foo
}
});
Copy this pattern for as many functions as you like. Then, in .ipython/<profile>/static/custom/custom.js, drag those out into something persistent:
$([IPython.events]).on('notebook_loaded.Notebook', function(){
require(['custom/myScript'], function(custom){
window.foo = custom.foo;
} );
});
Yes, I am a horrible person for throwing stuff on the window object, namespace things as you deem appropriate. But now in the notebook, a cell like
%%javascript
foo();
should do exactly what it looks like it should, without the user having to explicitly import your JS. I would love to see a simpler solution for this (plz devs can we plz have $.getScript('/static/custom/util.js'); in custom.js to load up a bunch of global JS functions) - but this is the best I've got for now. This singing and dancing aside, HUGE ups to the IPython notebook team, this is an awesome platform!
Not out of the box by installing a package, at least for now.
The way to do it is to use custom.js and jQuery getScript to inject the js into the notebook.
I explicitly stay vague on how to do it, as it is a dev feature changing from time to time.
What you should know is that the static folder in user profile is merged with webserver static assets allowing you to access any file that are in this folder by asking for the right url.
Also this question has been asked a few hours ago on IPython weekly video "lab meeting" broadcasted live and disponible on youtube (you might have a longer answer), I've opened discussion with the author of the question here
For some reason, I have problems with IPython.display.Javascript. Here is my alternative, which can handle both importing external .js files and running custom code:
from IPython.display import display, HTML
def javascript(*st,file=None):
if len(st) == 1 and file is None:
s = st[0]
elif len(st) == 0 and file is not None:
s = open(file).read()
else:
raise ValueError('Pass either a string or file=.')
display(HTML("<script type='text/javascript'>" + s + "</script>"))
Usage is as follows:
javascript('alert("hi")')
javascript(file='Gl.js')
javascript('echo("sdfds")')
You can use IJavascript (a Javascript kernel for Jupyter notebooks).
I was interested in calling JavaScript from a Jupyter code (Python) cell to process strings, and have the processed string output in the (same) code cell output; thanks to Inject/execute JS code to IPython notebook and forbid its further execution on page reload and Why cannot python call Javascript() from within a python function? now I have this example:
from IPython.display import display, Javascript, Markdown as md, HTML
def js_convert_str_html(instring_str):
js_convert = """
<div id="_my_special_div"></div>
<script>
var myinputstring = '{0}';
function do_convert_str_html(instr) {{
return instr.toUpperCase();
}}
document.getElementById("_my_special_div").textContent = do_convert_str_html(myinputstring);
</script>
""".format(instring_str)
return HTML(js_convert)
jsobj = js_convert_str_html("hello world")
display(jsobj)
Note that the JavaScript-processed string does not get returned to Python per se; rather, the JavaScript itself creates its own div, and adds the result of the string conversion to it.

"Error calling method on NPObject!" in Uploadify

I'm using Uploadify to upload file in my CMS. Everything works fine until recently. I got an error
Error calling method on NPObject
on this line
document.getElementById(jQuery(this).attr('id') + 'Uploader').startFileUpload(ID, checkComplete);
on this part
uploadifyUpload:function(ID,checkComplete) {
jQuery(this).each(function() {
if (!checkComplete) checkComplete = false;
document.getElementById(jQuery(this).attr('id') + 'Uploader').startFileUpload(ID, checkComplete);
});
},
I don't know why and after a day debugging and testing I found that if I remove replace(/\&/g, '\\&') from
String.prototype.escAll = function(){
var s = this;
return s.replace(/\./g, '\\.').replace(/\?/g, '\\?').replace(/\&/g, '\\&');
};
It then works again. I really don't know why.
Any helps would be appreciated!
I think the reason is in additional Javascript libraries you use.
Some libraries (for example Prototype.js or jQuery.js) change behaviour of your code. For example, you can't overload prototype in some cases. The result may be undefined in clear (obvious) places (like you use an array variable with wrong index). You should view the source code of additional libraries, probably they do with prototype something that breaks your code in the function you mentioned.
In my practice I had the situation when overloading of prototype worked incorrectly (it was String prototype like in your case).
So just don't use prototype.

Categories

Resources