I've got a webapp using Accusofts Prizm ActiveX Viewer to view and edit PDF's online. This product seems to work fine in every browser including edge except, you guessed it, Internet Explorer 11. I have been searching through the depths of the internet to try to find a solution to this and have found no useful results.
The error I am receiving is SCRIPT5022: SyntaxError with no further information on the error received which takes me to the following function with the 3rd line being the recipient of the error.
function createIconMap(iconText) {
var parser = new DOMParser();
var iconDoc = parser.parseFromString(iconText, 'image/svg+xml');
I have ran and compared IE against chrome and both inspectors are informing me they are behaving the same. Yet IE brakes on this function and Chrome goes on to display the PDF.
Please see the full JS below
// createIconMap
// Given an SVG as a string, parse it and extract the content of all
// symbol elements with an id.
function createIconMap(iconText) {
var parser = new DOMParser();
var iconDoc = parser.parseFromString(iconText, 'image/svg+xml');
var icons = iconDoc.getElementsByTagName('symbol');
function attributeReducer(memo, attr) {
return memo + ' ' + attr.name + '="' + attr.value + '"';
}
function childReducer(memo, node) {
if (node.nodeType !== 1) {
return memo;
}
// Build the DOM string of this node. Unfortunately, IE does
// not implement innerHTML, outerHTML, or any of the other
// content methods for SVG Elements and Node elements from
// the DOMParser.
return memo + '<' + node.tagName + ' ' +
_.reduce(node.attributes, attributeReducer, '') +
'>' +
(node.childNodes.length ? reduceNode(node) : '') +
'</' + node.tagName + '>';
}
function reduceNode(node) {
return _.reduce(node.childNodes, childReducer, '');
}
_.forEach(icons, function (icon) {
var id = icon.getAttribute('id');
if (!id) {
return;
}
ICON_MAP[id] = reduceNode(icon);
});
}
function Viewer(element, options) {
this.$dom
.html(_.template(options.template.viewer)(_.extend({
reasons: this.redactionReasonsExtended,
annotationsMode: options.annotationsMode,
downloadFormats: downloadFormats,
annotationFormats: annotationFormats
}, PCCViewer.Language.data)))
.addClass('pccv')
.show();
createIconMap(options.icons);
}
Please check the file (pdf, xml) content, might be the file contain the error description.
More details, you could refer to this sample.
Besides, according to this thread, you could try to use ActiveX to parse documents.
So, here's what has been found out as time has gone on. I have since found out that the Accusoft product doesn't work on IE 11 (64 bit version) which is the only version available on Windows 8+. I have also determined that putting the following in a Try/Catch will help enable it to work part of the time
var parser = new DOMParser();
var iconDoc = parser.parseFromString(iconText, 'image/svg+xml');
Related
Given the following code:
var hostUri = window.location.origin + '/GuestValidator.asmx/GetReservationInfo?resvNo=' + reservationno;
$.get(hostUri, {}, function (response) {
var data = response.documentElement.innerHTML;
}
If executed within a Chrome browser, the expected result returns a comma-delimited string of values within the innerHTML property of the documentElement object.
However, if the same code is executed using IE 11 or Edge there is no innerHTML property on the documentElement. It comes back as undefined.
But I can revise my code to response.documentElement.childNodes[0].data when executed within IE and get the same result that was present in Chrome using innerHTML.
I haven't tested the code with other browsers but I suspect they will likely have differences also.
So how can this code be revised to acquire what would be the innerHTML value within Chrome across all browsers without having to execute separate code based on the browser?
EDITED FOR CLARITY
This is an excerpt of the web method. It is returning a generic list of type string. It doesn't matter whether or not I return a JSON object.
var arry = new List<string>();
var blockedOrderDays = 3;
var blockedDay = String.Empty;
var noOrderDays = String.Empty;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var svclient = new ServiceClient();
var result = svclient.GetReservation(reservationNo);
var details = result.Reservation.ArrivalDate;
var arrivalDt = formatDate(details);
while(blockedOrderDays != 0)
{
blockedDay = formatDate(details.AddDays(-blockedOrderDays));
arry.Add(blockedDay);
noOrderDays += blockedDay + ",";
-- blockedOrderDays;
++x;
}
arry.Add(arrivalDt);
noOrderDays = noOrderDays + arrivalDt;
return noOrderDays;
After spending some additional time and effort on getting this code to work with a reasonable level of continuity across browser platforms. The following modification appears to have resolved the issue.
var hostUri = window.location.origin + '/GuestValidator.asmx/GetReservationInfo?resvNo=' + reservationno;
$.get(hostUri, {}, function (response) {
if ((navigator.userAgent.indexOf("MSIE") !== -1) || (!!document.documentMode === true))
prohibitOrderDates = response.childNodes[0].textContent;
else
prohibitOrderDates = response.children[0].innerHTML;
var data = response.children[0].innerHTML;
}
Alternatively, though not specific to the answer. A shortened version of the call can be:
var hostUri = window.location.origin + '/GuestValidator.asmx/GetReservationInfo';
$.get(hostUri, { resvNo=reservationno }, function (response) {
if ((navigator.userAgent.indexOf("MSIE") !== -1) || (!!document.documentMode === true))
prohibitOrderDates = response.childNodes[0].textContent;
else
prohibitOrderDates = response.children[0].innerHTML;
var data = response.children[0].innerHTML;
}
So the response.children[0].innerHTML is the appropriate call to retain browser continuity for most every browser I've tested and IE always seems to be the exception to the rule. Even Microsoft Edge follows the standard. IE seems to be an odd ball for ever keeping standard.
On the script below, IE9 is throwing an error:
SCRIPT5022: DOM Exception: INVALID_CHARACTER_ERR (5)
mootools-1.2.1-core-yc.js, line 118 character 1
Document.implement({
newElement: function (A, B) {
if (Browser.Engine.trident && B) {
["name", "type", "checked"].each(function (C) {
if (!B[C]) {
return;
}
A += " " + C + '="' + B[C] + '"';
if (C != "checked") {
delete B[C];
}
});
A = "<" + A + ">";
}
return $.element(this.createElement(A)).set(B); //THIS IS LINE 118
},
newTextNode: function (A) {
return this.createTextNode(A);
},
getDocument: function () {
return this;
},
getWindow: function () {
return this.window;
}
});
This snippet is part of the Mootools js library that the developer used on the site. Is there a workaround to fix the error for IE?
yeah that code is garbage, you should never do browser checks like that, its taught in JavaScript 101... lol can't believe that's in mootools? blech, anyways
IE9 doesn't allow for crazy document.createElement('<div style="background:red">yay!</div>'); syntax anymore (no one should've ever really been using it in the first place...)
here's an example:
var d = document;
var x = d.createElement('div');
x.innerHTML = 'yay';
x.style.backgroundColor = 'red';
x.style.padding = '6px';
x.style.margin = '20px';
d.body.appendChild(x);
var sameHTML = '<div style="background:green;padding:6px;margin:20px;">yay!</div>';
// fails in IE > 8 and other browsers
try {
var y = d.createElement(sameHTML);
d.body.appendChild(y);
} catch (err) {
d.body.appendChild(d.createTextNode(err));
}
// quick fix using innerHTML:
var temp = d.createElement('div');
temp.innerHTML = sameHTML;
d.body.appendChild(temp.childNodes[0]);
the way to fix this is to either create a dummy element and use .innerHTML and then extract the child, or inside mootools check the browser version and don't do that for IE > 8 if i remember right mootools has a Browser.Engine.version or something to that effect...
edit: i feel like i should also add that this: Browser.Engine.trident is the problematic check, and from the gyst of the code looks like it might occur else where too...
aha! another update:
i found this while looking through [an old] support thread:
you'll need to update to 1.2.5 or 1.3. Previous MooTools versions are not supported by IE9.
so an update to the script should fix your problem, hopefully it won't introduce more bugs... you can get it here: http://mootools.net/download, you might want to try that 1.2.5 version at the top of the page since it will have the least amount of changes...
good luck -ck
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
How can i write a console log wrapper that:
Keeping the recorded line number and file name of the log statement intact
Provides access to all log severity methods (error, log, debug, ...) and shows them in the console as they where logged
does provide some fallback (for example calls the log method when the browser does not support error)
can be switched off in a central location, so I can switch off logging for production
does handle the case that no console exists, and does not throw errors
Since logging in Java Script is so inconsistent, there must be some solution. Implementing it myself is a little bit tedious, but there seems to be no good library.
I currently found this logger that provides all the features, but it does mess up the line numbers. http://benalman.com/projects/javascript-debug-console-log/
There is my own log4javascript, which has its own logging console but also provides a wrapper around console.log. It fulfils all your criteria except keeping line numbers intact, which is impossible to achieve if you're wrapping calls to console.log() etc. in another function.
var log = log4javascript.getLogger("main");
var appender = new log4javascript.BrowserConsoleAppender();
log.addAppender(appender);
log.debug("Hello world");
I would also recommend log4javascript and explain how you can still keep the information about the printed filename and line, at least in Chrome.
I am not talking about changing the filename and line printed by Chrome but you can get to the information you are interested in and append it to the log statement.
My solution has been a quick hack but I think with a little more work you can get nicely formatted log statements.
It probably has also a heavy performance-impact, but since you won't leave your logs activated in production this shouldn't be too much of a problem.
The Concept
In Chrome you can create an Error object which provides a stack property that shows you your current stack location and somewhere in the stack string you find the file and line number of your calling script.
> new Error().stack
"Error
at eval at <anonymous> (eval at evaluate (unknown source))
at eval at evaluate (unknown source)
at FrameMirror.evaluate (native)
at Object.evaluate (unknown source)
at Object._evaluateOn (unknown source)
at Object._evaluateAndWrap (unknown source)
at Object.evaluateOnCallFrame (unknown source)
at meinAjaxAufruf (http://localhost:8080/numberajax.js:21:9)
at HTMLInputElement.onkeyup (http://localhost:8080/numberajax.html:15:188)"
For a log4javascript call the stack trace might look something like this:
"Error
at Object.append (http://localhost:8080/log4javascript_uncompressed.js:1921:17)
at Object.doAppend (http://localhost:8080/log4javascript_uncompressed.js:1047:9)
at Object.callAppenders (http://localhost:8080/log4javascript_uncompressed.js:647:27)
at Object.log (http://localhost:8080/log4javascript_uncompressed.js:640:10)
at Object.debug (http://localhost:8080/log4javascript_uncompressed.js:748:9)
at meinAjaxAufruf (http://localhost:8080/numberajax.js:36:16)
at HTMLInputElement.onkeyup (http://localhost:8080/numberajax.html:16:188)"
And the file and line that made the log4javascript call and that i am interested in is
at meinAjaxAufruf (http://localhost:8080/numberajax.js:36:16)
The Solution
I am guessing that the stack depth from the script your interested in to where the actual console call happens is always the same. So now you simply have to find out where the BrowserConsoleAppender makes its window.console access and add the line you are interested in to the formatted string. I did the following changes to log4javascript_uncompressed.js (version 1.4.2 line 1913):
} else if (window.console && window.console.log) { // Safari and Firebug
var formattedMesage = getFormattedMessage();
//---my additions
var isChrome = navigator.userAgent.indexOf("Chrome") !== -1;
if(isChrome){
var stack = new Error().stack;
var lineAccessingLogger = stack.split("\n")[6];
formattedMesage += "\n" + lineAccessingLogger;
}
//---
// Log to Firebug using its logging methods or revert to the console.log
// method in Safari
if (window.console.debug && Level.DEBUG.isGreaterOrEqual(loggingEvent.level)) {
window.console.debug(formattedMesage);
} else if (window.console.info && Level.INFO.equals(loggingEvent.level)) {
...
Now instead of
17:53:22,872 DEBUG - sending /NumberServlet?zahl=1&text=
log4javascript.js:154
I get
17:55:53,008 DEBUG - sending /NumberServlet?zahl=1&text=
at meinAjaxAufruf (http://localhost:8080/numberajax.js:36:16) log4javascript_uncompressed.js:1930
It sure isn't a nice solution :), but I get what I need.
With a little more knowledge of the framework I suppose one could change the PatternLayout in a way that you can define how to print the file name/location and line number.
edit Instead of my prior solution I made some modifications to the PatternLayout.prototype.format function, so now I can use the additional option %l to define where and how I want to output the calling file and its line. I published my changes and a usage example as a Gist.
We had this issue with our log wrapper also and it turns out there is a fantastic, simple workaround using partial function application:
if(DEBUG_ENABLED && (typeof console != 'undefined')) {
this.debug = console.log.bind(console);
}
else {
this.debug = function(message) {};
}
With this, your browser will detect the correct line number and file of the source you wanted to log.
Crossposting from related question (A proper wrapper for console.log with correct line number?) but with updated solution to address multiple methods.
I liked #fredrik's answer, so I rolled it up with another answer which splits the Webkit stacktrace, and merged it with #PaulIrish's safe console.log wrapper. "Standardizes" the filename:line to a "special object" so it stands out and looks mostly the same in FF and Chrome.
Testing in fiddle: http://jsfiddle.net/drzaus/pWe6W/9/
_log = (function (methods, undefined) {
var Log = Error; // does this do anything? proper inheritance...?
Log.prototype.write = function (args, method) {
/// <summary>
/// Paulirish-like console.log wrapper. Includes stack trace via #fredrik SO suggestion (see remarks for sources).
/// </summary>
/// <param name="args" type="Array">list of details to log, as provided by `arguments`</param>
/// <param name="method" type="string">the console method to use: debug, log, warn, info, error</param>
/// <remarks>Includes line numbers by calling Error object -- see
/// * http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
/// * https://stackoverflow.com/questions/13815640/a-proper-wrapper-for-console-log-with-correct-line-number
/// * https://stackoverflow.com/a/3806596/1037948
/// </remarks>
// via #fredrik SO trace suggestion; wrapping in special construct so it stands out
var suffix = {
"#": (this.lineNumber
? this.fileName + ':' + this.lineNumber + ":1" // add arbitrary column value for chrome linking
: extractLineNumberFromStack(this.stack)
)
};
args = args.concat([suffix]);
// via #paulirish console wrapper
if (console && console[method]) {
if (console[method].apply) { console[method].apply(console, args); } else { console[method](args); } // nicer display in some browsers
}
};
var extractLineNumberFromStack = function (stack) {
/// <summary>
/// Get the line/filename detail from a Webkit stack trace. See https://stackoverflow.com/a/3806596/1037948
/// </summary>
/// <param name="stack" type="String">the stack string</param>
// correct line number according to how Log().write implemented
var line = stack.split('\n')[3];
// fix for various display text
line = (line.indexOf(' (') >= 0
? line.split(' (')[1].substring(0, line.length - 1)
: line.split('at ')[1]
);
return line;
};
// method builder
var logMethod = function(method) {
return function (params) {
/// <summary>
/// Paulirish-like console.log wrapper
/// </summary>
/// <param name="params" type="[...]">list your logging parameters</param>
// only if explicitly true somewhere
if (typeof DEBUGMODE === typeof undefined || !DEBUGMODE) return;
// call handler extension which provides stack trace
Log().write(Array.prototype.slice.call(arguments, 0), method); // turn into proper array & declare method to use
};//-- fn logMethod
};
var result = logMethod('log'); // base for backwards compatibility, simplicity
// add some extra juice
for(var i in methods) result[methods[i]] = logMethod(methods[i]);
return result; // expose
})(['error', 'debug', 'info', 'warn']);//--- _log
To keep it simple, I've the below wrapper for console methods:
var noop = function () {};
window.consolex = {
debug : window.console && window.console.debug && console.debug.bind(console) || noop,
log : window.console && window.console.log && console.log.bind(console) || noop,
warn: window.WARN = window.console && window.console.warn && console.warn.bind(console) || noop,
error: window.ERROR = window.console && window.console.error && console.error.bind(console) || noop
};
Also, for better logs in IE and older browsers, please read: Detailed console logging
Google Chrome will soon have a feature that will be of interest to this thread.
You can enable it now by:
Enable chrome://flags/#enable-devtools-experiments
Click on cog in dev tools
Go to Experiments Tab
Check "Javascript frameworks debugging"
Go to General Tab
Under the Sources section
Check "Skip stepping through sources with particular names"
In the pattern inputbox: type in the file name that you see now (app.log.js)
Restart and enjoy :)
References:
Tests from chrom devtools
devtools Issues thread
devtools code review
I answered this question here, but in short see the codepen for full implementation. However, this does everything you want, cross browser, no errors, correct line numbers, all available console methods, global and local control:
var Debugger = function(gState, klass) {
this.debug = {}
if (!window.console) return function(){}
if (gState && klass.isDebug) {
for (var m in console)
if (typeof console[m] == 'function')
this.debug[m] = console[m].bind(window.console, klass.toString()+": ")
}else{
for (var m in console)
if (typeof console[m] == 'function')
this.debug[m] = function(){}
}
return this.debug
}
And use it like this:
isDebug = true //global debug state
debug = Debugger(isDebug, this)
debug.log('Hello Log!')
I found a solution (requires jquery) somehwere on the Web but it does not work in most browsers.
I changed it and it works in Firefox (Mac, Linux. Android), Chrome (Mac, Linux. Android) and Safari and other Android webkit browsers.
Just write the following code to a file called e.g. debug.js and include it after the inclusion of 'jquery.js' in the <head> section of your webpage and it will work after the page has loaded (document.ready). I still have to find out to allow debugging before everything is loaded (e.g. only the <head>...</head> ).
The webpage has to be called with ?d=1 in the URL and when using Safari ?d=1s as I cannot make a distinction between Safari and another Webkit browser in the user agent and Safari has a different behavior in line number and file name handling than other Webkit browsers.
The function p_r(expression) logs to the window of the id #js_debug and to the console (if opened) with the file name and line number.
var g_d = null;
function sortObj(theObj)
{
var sortable = [];
for (var i in theObj) {
sortable.push(i);
}
sortable.sort();
var copy = new Object;
for (var i in sortable) {
var ind = sortable[i];
copy[ind] = theObj[ind];
}
return copy;
}
function p_r(s, comment, level)
{
if (!g_d) return;
var res = s;
var pre = new Array(""," " , " ", " ", " ");
if (comment) comment += ' : ';
if (arguments.length<2) comment='';
if (arguments.length<3) level = 0;
// if (console) console.log(s);
if (typeof(s) == 'object') {
var copy = sortObj(s);
comment += '\n';
res = '[object]\n';
if (level < 2) {
for (var i in copy) {
if (typeof(copy[i]) != "function")
res += pre[level] + (i) + " : " + p_r(copy[i], '', level+1) + " : " + typeof(copy[i]) + "\n";
}
res += pre[level] + "[/object]\n";
}
}
else if (typeof(s) == 'function')
res = 'function';
else if (typeof(s) != 'string')
res = '' + s;
res = res.replace(/&/g, '&');
res = res.replace(/\x3C/g, '<');
res = res.replace(/>/g, '>');
if (level == 0) {
window.LOG=res;
console.log(window.LOG + comment + res);
g_d.innerHTML += (window.LOG + comment + res + '\n');
}
return res;
}
if (location.href.match(/d\=[1-9]/)) {
$(document).ready(function() {
$("body").prepend("<div id=\"js_debugclick\" onclick=\"$('#js_debug').toggle();\">JS DEBUG</div>\
<pre onclick=\"$('#js_debug').toggle();\" id='js_debug'></pre>\
");
$("head").append("<style type=\"text/css\">\
pre#js_debug {\
border: solid black 1px; background-color: #1CF; color: #000; display:none; position:absolute; top: 20px;\
font-family: Lucida Console, monospace; font-size: 9pt; height: 400px; overflow:scroll; width:100%;\
z-index:100;\
} \
#js_debugclick { \
color:red; font-weight:bold; \
} \
</style>\
");
g_d = document.getElementById('js_debug');
});
var __moredebug = location.href.match(/d\=[2-9]/);
var __issafari = /safari/.test(navigator.userAgent.toLowerCase()) && location.href.match(/d\=[1-9]s/);
var __iswebkit = /webkit/.test(navigator.userAgent.toLowerCase());
var __isopera = /opera/.test(navigator.userAgent.toLowerCase());
if (__moredebug) console.log(__issafari, __iswebkit);
/*#const*/ //for closure-compiler
//DEBUG=2 // 0=off, 1=msg:file:line:column, 2=msg:stack-trace
/*#const #constructor*/
Object.defineProperty(window,'__stack__',{get:function(){
try{i.dont.exist()}catch(e){
if (__moredebug) var x=e.stack.split(":"); for (i in x){console.log(i,x[i]);}
// console.log(e.stack.split(":")[13].match(/(\d+)/)[1]);
return e.stack.split(":")}
}})
/*#const #constructor*/
Object.defineProperty(window,'__file__',{get:function(){
var s=__stack__,l=s.length
var f= __issafari ? s[9] : (__isopera ? s[12] : (__iswebkit ? s[14] : s[9]));
return f.replace(/^.+?\/([^\/]+?)\?.+?$/, "$1");
}})
/*#const #constructor*/
Object.defineProperty(window,'__line__',{get:function(){
var s=__stack__,l=s.length
return __issafari ? s[10].match(/(\d+)/)[1] :(__isopera ? s[13].match(/(\d+)/)[1] : (__iswebkit ? s[15] : s[10].replace(/\n/, " ").replace(/(\d+).+?$/, "$1")));
}})
/*#const #constructor*/
Object.defineProperty(window,'__col__',{get:function(){
var s=__stack__,l=s.length
return (isNaN(s[l-2]))?"NA":s[l-1]
}})
/*#const #constructor*/
Object.defineProperty(window,'LOG',{
get:function(){return out},
set:function(msg){if(0)out=msg+"\t-\t"+__stack__
else out=__file__+" "+__line__+": ";
}
})
}//end if(DEBUG)
I have this
authnav='<li class="last">login</li>'+
'<li>create account</li>';
It works fine in Firefox, but Internet Explorer gives me an "Error: Object doesn't support this property or method" I'm mystified - what could be going on here?
There's a comment line above the offending line, could that possibly be making a difference?
//authnav='<li class="last">login</li>';
Check out the page yourself at http://www.imagineelection.com. I want two little links, "login" and "create account", to appear on the top right of the page.
Thanks!
The problem arises in this function as IE allows you to reference document.getElementById("authnav") as authnav and then gets upset when you assign it a string. Maybe declaring a local variable explicitly with var authnav will work or is it intended to be a global variable?
function add_auth_nav() {
name = get_cookie("name");
candidate = get_cookie("candidate");
if (name) {
authnav = '<li class="last">logout</li>';
if (candidate) {
authnav = authnav + '<li>edit profile</li><li>view profile</li>'
}
authnav = authnav + "<li>" + name.replace(/\+/g, " ") + "</li>"
} else {
authnav = '<li class="last">login</li><li>create account</li>'
}
document.getElementById("authnav").innerHTML = authnav
}
Results reproduced. Can you substitute the ie_scripts.min.js file with the original and check if it still fails...
I'm pretty sure the answer is no, but thought I'd ask anyway.
If my site references a scripted named "whatever.js", is it possible to get "whatever.js" from within that script? Like:
var scriptName = ???
if (typeof jQuery !== "function") {
throw new Error(
"jQuery's script needs to be loaded before " +
scriptName + ". Check the <script> tag order.");
}
Probably more trouble than it's worth for dependency checking, but what the hell.
var scripts = document.getElementsByTagName('script');
var lastScript = scripts[scripts.length-1];
var scriptName = lastScript.src;
alert("loading: " + scriptName);
Tested in: FF 3.0.8, Chrome 1.0.154.53, IE6
See also: How may I reference the script tag that loaded the currently-executing script?
I'm aware this is old but I have developed a better solution because all of the above didn't work for Async scripts. With some tweaking the following script can cover almost all use cases. Heres what worked for me:
function getScriptName() {
var error = new Error()
, source
, lastStackFrameRegex = new RegExp(/.+\/(.*?):\d+(:\d+)*$/)
, currentStackFrameRegex = new RegExp(/getScriptName \(.+\/(.*):\d+:\d+\)/);
if((source = lastStackFrameRegex.exec(error.stack.trim())) && source[1] != "")
return source[1];
else if((source = currentStackFrameRegex.exec(error.stack.trim())))
return source[1];
else if(error.fileName != undefined)
return error.fileName;
}
Not sure about support on Internet Explorer, but works fine in every other browser I tested on.
You can use...
var scripts = document.getElementsByTagName("script"),
currentScriptUrl = (document.currentScript || scripts[scripts.length - 1]).src;
currentScript() is supported by all browsers except IE.
Make sure it's ran as the file is parsed and executed, not on DOM ready or window load.
If it's an empty string, your script block has no or an empty src attribute.
In Node.js:
var abc = __filename.split(__dirname+"/").pop();
Shog9's suggestion more shorter:
alert("loading: " + document.scripts[document.scripts.length-1].src);
You can return a list of script elements in the page:
var scripts = document.getElementsByTagName("script");
And then evaluate each one and retrieve its location:
var location;
for(var i=0; i<scripts.length;++i) {
location = scripts[i].src;
//Do stuff with the script location here
}
As the "src" attribute holds the full path to the script file you can add a substring call to get the file name only.
var path = document.scripts[document.scripts.length-1].src;
var fileName = path.substring(path.lastIndexOf('/')+1);
I had issues with the above code while extracting the script name when the calling code is included inside a .html file.
Hence I developed this solution:
var scripts = document.getElementsByTagName( "script" ) ;
var currentScriptUrl = ( document.currentScript || scripts[scripts.length - 1] ).src ;
var scriptName = currentScriptUrl.length > 0 ? currentScriptUrl : scripts[scripts.length-1].baseURI.split( "/" ).pop() ;
You can try putting this at the top of your JavaScript file:
window.myJSFilename = "";
window.onerror = function(message, url, line) {
if (window.myJSFilename != "") return;
window.myJSFilename = url;
}
throw 1;
Make sure you have only functions below this. The myJSFilename variable will contain the full path of the JavaScript file, the filename can be parsed from that. Tested in IE11, but it should work elsewhere.
If you did't want use jQuery:
function getCurrentFile() {
var filename = document.location.href;
var tail = (filename.indexOf(".", (filename.indexOf(".org") + 1)) == -1) ? filename.length : filename.lastIndexOf(".");
return (filename.lastIndexOf("/") >= (filename.length - 1)) ? (filename.substring(filename.substring(0, filename.length - 2).lastIndexOf("/") + 1, filename.lastIndexOf("/"))).toLowerCase() : (filename.substring(filename.lastIndexOf("/") + 1, tail)).toLowerCase();
}
What will happen if the jQuery script isn't there? Are you just going to output a message? I guess it is slightly better for debugging if something goes wrong, but it's not very helpful for users.
I'd say just design your pages such that this occurrence will not happen, and in the rare event it does, just let the script fail.
The only way that is waterproof:
var code = this.__proto__.constructor.toString();
$("script").each(function (index, element) {
var src = $(element).attr("src");
if (src !== undefined) {
$.get(src, function (data) {
if (data.trim() === code) {
scriptdir = src.substring(0, src.lastIndexOf("/"));
}
});
}
});
"var code" can also be the function name, but with the prototype constructor you don't have to modify anything. This code compares its own content against all present scripts. No hard coded filenames needed anymore.
Korporal Nobbs was in the right direction, but not complete with the comparison.