I'm not sure I really understand why this is being treated this way - is it because fetch tries to encode all variables? If so how do I fix it?
This fetch URL will work when the only variables I put into it are coordinates (numbers). In my overall code, I have a string that I encoded myself from an array that can have a varying bracket structure, so that is the reasoning.
When I copy and paste this into a browser and paste in my variable where it should go, it works. But the fetch doesn't work.
Is fetch trying to do something more to my variable that already has encoding? I don't understand, because the non-variable part of the string is already encoded, so I'm assuming the issue has to do with how fetch is treating the variable.
Anyway, see the structure where the variable is in my URL too, I guess (sorry it's long):
JS:
let testString = "%5B%5B%5B-89.0000%2C40.5555%5D%2C%5B-89.1111%2C40.5555%5D%5D%5D";
fetch('https://hazards.fema.gov/gis/nfhl/rest/services/FIRMette/NFHLREST_FIRMette/MapServer/1/query?where=&text=&objectIds=&time=&geometry=%7B%22paths%22%3A+' + testString + '%7D&geometryType=esriGeometryPolyline&inSR=4326&spatialRel=esriSpatialRelIntersects&distance=&units=esriSRUnit_Foot&relationParam=&outFields=*&returnGeometry=false&returnTrueCurves=false&maxAllowableOffset=&geometryPrecision=&outSR=&havingClause=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&historicMoment=&returnDistinctValues=false&resultOffset=&resultRecordCount=&returnExtentOnly=false&datumTransformation=¶meterValues=&rangeValues=&quantizationParameters=&featureEncoding=esriDefault&f=pjson')
.then(function (response) {
return response.json();
})
.then (function (data) {
appendData(data);
})
.catch(function (err) {
console.log('error: ' + err);
});
Edit: I even tried straight up running the fetch with the string from my variable, and it worked. So it has to do with the variable - it just doesn't make much sense.
My full messy testing code (add the coordinates to list then run)
Edit 2: See my below answer. In my actual code I had add/remove options functionality that was causing an issue in my function to fetch the data. I needed these options to build my string used in the fetch. I used preventDefault() to fix the problem - but I'm still not positive on why it works with that specifically.
I found my issue, so I'm answering my question - I welcome any explanation though.
I posted a jsfiddle of my code but it's a mess, but to sum up what was going on:
I had a list of options that the user could add to add coordinates, and then run those. In my problem code, these options were referenced under a GetData() function which ran my fetch. Outside of that GetData() function, these options were created, but I didn't think that was the problem because the brackets were closed around both the add and remove an option functionalities.
I had a button for add, and a button for remove. These functionalities were made, for example, with:
btnRemove.onclick = (e) => {
e.preventDefault();
// add/remove/getselected/etc functionalities here
}
I created a function just like this to replace my GetData() function, reading:
linearGPSsubmit.onclick = (e) => {
e.preventDefault();
}
The preventDefault() was originally to help aid the add/remove functionality.
That code above executes on submit button click. What I don't fully understand is why the fetch runs at all when preventDefault() is used? Shouldn't it stop me from submitting the form? Nevertheless... no more 404 and the fetch fetches. Cool. It feels wrong, but it works.
Mid development I decided to switch to server-side rendering for a better control amongst other benefits. My web application is completely AJAX based, no url redirecting, so the idea here is a website that builds itself up
I just couldn't figure out the proper way to send javascript events/functions along with the html string, or should all the necessary javascript always be preloaded in the static files?
Let's say client clicks a pre-rendered button 'open table'
The server will make a query, build the html table and send it back, but this table also needs javascript triggers and functions to work properly, how are these sent, received and executed?
There are a couple of articles that mention to not use eval() in Javascript, is there any way around this? I don't want to have to preload unnecessary events for elements that don't yet exist
The server is Python and the Client is Javascript/JQuery
Theoretical example :
Client Base Javascript :
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
$("#table_div").append(response.html);
eval(response.javascript()); //??
}
});
Python Server(views.py) :
def get_table(request):
data = {}
#String containing rendered html
data['html'] = get_render_table()
#String containing Javascript code?
data['javascript'] = TABLE_EVENTS_JAVASCRIPT
return HttpResponse(json.dumps(data),content_type='json')
Worth noting my question comes from an experimental/learning perspective
Update:
You can use jQuery.getScript() to lazy load JS. I think this solution is as close as you can get to run JS without using eval().
See this example:
jQuery.getScript("/path/to/script.js", function(data, textStatus, jqxhr) {
/* Code has been loaded and executed. */
console.log( data ); // Data returned
console.log( textStatus ); // Success
console.log( jqxhr.status ); // 200
console.log( "Load was performed." );
});
and "/path/to/script.js" could be a string returned from $.getJOSN response.
Also, the documentation for getScrippt() has examples on how to handle errors and cache files.
Old Answer:
Using .on() attaches events to current and future DOM elements.
You can either attache events prior to DOM insertion or attache event after DOM insertion.
So in your example you can do something like:
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
var code = $(response.html);
code.find(".elementToFind").on("click", function (){
// Code to be executed on click event
});
$("#table_div").append(code);
}
});
I did not test the code but I think it should work.
Assuming you can't just set up an event-binding function and then call it from the main script (the JavaScript you need can't be guessed ahead of time, for example) then one really easy way is just to append the JavaScript to the bottom of the returned HTML content within script tags. When it's appended along with the HTML, the script should simply execute, with no eval() required.
I can't swear that this would work in old browsers, but it's a trick I've used a couple of times, and I've had no problems with it in Firefox, Chrome, or any of the later IE versions.
I think I see what you're asking here, from my understanding you want to send the new "page" asynchorously, and render the new javascript and html. It looks like you already got your request/response down, so i'm not gonna go and talk about sending JSON objects, and the whole "how-to" of sending html and javascript because it looks like you got that part. To do what you want and to dynamically add your javascript in, this stackoverflow question looks like it has what you need
Is there a way to create a function from a string with javascript?
So pertaining to your example, here is how it would look when you recieve the JSON string from your python script:
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
$("#table_div").append(response.html);
/* Create function from string */
var newFunction = Function(response.javascript['param_1'], response.javascript['param_2'], response.javascript['function']);
/* Execute our new function to test it */
newFunction();
}
});
*Your actual function contents would be the string: response.javascript['function']
*Your parameter names if any would be in separate strings ex: response.javascript['param_1']
That is almost a direct copy of the "String to function" code that you can see in the linked question, just replaced it with your relevant code. This code is also assuming that your object is sent with the response.javascript object containing an array with your actual function content and parameter names. I'm sure you could change the actual name of the var too, or maybe put it in an associative array or something that you can keep track of and rename. All just suggestions, but hopefully this works for you, and helps you with your problem.
I am also doing similar work in my project where I had to load partial html using ajax calls and then this partial HTML has elements which requires events to be attached. So my solution is to create a common method to make ajax calls and keep a js method name to be executed post ajax call in html response itself. For example my server returns below html
<input type="hidden" data-act="onPartialLoad" value="createTableEvents" />
<div>.........rest of html response.....<div>
Now in common method, look for input[type='hidden'][data-act='onPartialLoad'] and for each run the method name provided in value attribute (value="createTableEvents")
Dont Use Eval() method as it is not recommended due to security
issues. Check here.
you can run js method using window["method name"]...so here is a part of code that I use.
$.ajax(options).done(function (data) {
var $target = $("#table_div");
$target.fadeOut(function () {
$target.html(data);
$target.fadeIn(function () {
try {
$('input[data-act="onPartialLoad"]', $target).each(function () {
try {
//you can pass parameters in json format from server to be passed into your js method
var params = $(this).attr('params');
if (params == undefined) {
window[$(this).val()]();
}
else {
window[$(this).val()]($.parseJSON(htmlutil.htmlDecode(params)));
}
} catch (e) {
if (console && console.log) {
console.log(e.stack);
console.log($(this).val());
}
}
});
}
catch (e) {
console.log(e.stack);
}
});
});
});
use jQuery.getScript() (as suggested by Kalimah Apps) to load the required js files first.
So apparently because of the recent scams, the developer tools is exploited by people to post spam and even used to "hack" accounts. Facebook has blocked the developer tools, and I can't even use the console.
How did they do that?? One Stack Overflow post claimed that it is not possible, but Facebook has proven them wrong.
Just go to Facebook and open up the developer tools, type one character into the console, and this warning pops up. No matter what you put in, it will not get executed.
How is this possible?
They even blocked auto-complete in the console:
I'm a security engineer at Facebook and this is my fault. We're testing this for some users to see if it can slow down some attacks where users are tricked into pasting (malicious) JavaScript code into the browser console.
Just to be clear: trying to block hackers client-side is a bad idea in general;
this is to protect against a specific social engineering attack.
If you ended up in the test group and are annoyed by this, sorry.
I tried to make the old opt-out page (now help page) as simple as possible while still being scary enough to stop at least some of the victims.
The actual code is pretty similar to #joeldixon66's link; ours is a little more complicated for no good reason.
Chrome wraps all console code in
with ((console && console._commandLineAPI) || {}) {
<code goes here>
}
... so the site redefines console._commandLineAPI to throw:
Object.defineProperty(console, '_commandLineAPI',
{ get : function() { throw 'Nooo!' } })
This is not quite enough (try it!), but that's the
main trick.
Epilogue: The Chrome team decided that defeating the console from user-side JS was a bug and fixed the issue, rendering this technique invalid. Afterwards, additional protection was added to protect users from self-xss.
I located the Facebook's console buster script using Chrome developer tools. Here is the script with minor changes for readability. I have removed the bits that I could not understand:
Object.defineProperty(window, "console", {
value: console,
writable: false,
configurable: false
});
var i = 0;
function showWarningAndThrow() {
if (!i) {
setTimeout(function () {
console.log("%cWarning message", "font: 2em sans-serif; color: yellow; background-color: red;");
}, 1);
i = 1;
}
throw "Console is disabled";
}
var l, n = {
set: function (o) {
l = o;
},
get: function () {
showWarningAndThrow();
return l;
}
};
Object.defineProperty(console, "_commandLineAPI", n);
Object.defineProperty(console, "__commandLineAPI", n);
With this, the console auto-complete fails silently while statements typed in console will fail to execute (the exception will be logged).
References:
Object.defineProperty
Object.getOwnPropertyDescriptor
Chrome's console.log function (for tips on formatting output)
I couldn't get it to trigger that on any page. A more robust version of this would do it:
window.console.log = function(){
console.error('The developer console is temp...');
window.console.log = function() {
return false;
}
}
console.log('test');
To style the output: Colors in JavaScript console
Edit Thinking #joeldixon66 has the right idea: Disable JavaScript execution from console « ::: KSpace :::
Besides redefining console._commandLineAPI,
there are some other ways to break into InjectedScriptHost on WebKit browsers, to prevent or alter the evaluation of expressions entered into the developer's console.
Edit:
Chrome has fixed this in a past release. - which must have been before February 2015, as I created the gist at that time
So here's another possibility. This time we hook in, a level above, directly into InjectedScript rather than InjectedScriptHost as opposed to the prior version.
Which is kind of nice, as you can directly monkey patch InjectedScript._evaluateAndWrap instead of having to rely on InjectedScriptHost.evaluate as that gives you more fine-grained control over what should happen.
Another pretty interesting thing is, that we can intercept the internal result when an expression is evaluated and return that to the user instead of the normal behavior.
Here is the code, that does exactly that, return the internal result when a user evaluates something in the console.
var is;
Object.defineProperty(Object.prototype,"_lastResult",{
get:function(){
return this._lR;
},
set:function(v){
if (typeof this._commandLineAPIImpl=="object") is=this;
this._lR=v;
}
});
setTimeout(function(){
var ev=is._evaluateAndWrap;
is._evaluateAndWrap=function(){
var res=ev.apply(is,arguments);
console.log();
if (arguments[2]==="completion") {
//This is the path you end up when a user types in the console and autocompletion get's evaluated
//Chrome expects a wrapped result to be returned from evaluateAndWrap.
//You can use `ev` to generate an object yourself.
//In case of the autocompletion chrome exptects an wrapped object with the properties that can be autocompleted. e.g.;
//{iGetAutoCompleted: true}
//You would then go and return that object wrapped, like
//return ev.call (is, '', '({test:true})', 'completion', true, false, true);
//Would make `test` pop up for every autocompletion.
//Note that syntax as well as every Object.prototype property get's added to that list later,
//so you won't be able to exclude things like `while` from the autocompletion list,
//unless you wou'd find a way to rewrite the getCompletions function.
//
return res; //Return the autocompletion result. If you want to break that, return nothing or an empty object
} else {
//This is the path where you end up when a user actually presses enter to evaluate an expression.
//In order to return anything as normal evaluation output, you have to return a wrapped object.
//In this case, we want to return the generated remote object.
//Since this is already a wrapped object it would be converted if we directly return it. Hence,
//`return result` would actually replicate the very normal behaviour as the result is converted.
//to output what's actually in the remote object, we have to stringify it and `evaluateAndWrap` that object again.`
//This is quite interesting;
return ev.call (is, null, '(' + JSON.stringify (res) + ')', "console", true, false, true)
}
};
},0);
It's a bit verbose, but I thought I put some comments into it
So normally, if a user, for example, evaluates [1,2,3,4] you'd expect the following output:
After monkeypatching InjectedScript._evaluateAndWrap evaluating the very same expression, gives the following output:
As you see the little-left arrow, indicating output, is still there, but this time we get an object. Where the result of the expression, the array [1,2,3,4] is represented as an object with all its properties described.
I recommend trying to evaluate this and that expression, including those that generate errors. It's quite interesting.
Additionally, take a look at the is - InjectedScriptHost - object. It provides some methods to play with and get a bit of insight into the internals of the inspector.
Of course, you could intercept all that information and still return the original result to the user.
Just replace the return statement in the else path by a console.log (res) following a return res. Then you'd end up with the following.
End of Edit
This is the prior version which was fixed by Google. Hence not a possible way anymore.
One of it is hooking into Function.prototype.call
Chrome evaluates the entered expression by calling its eval function with InjectedScriptHost as thisArg
var result = evalFunction.call(object, expression);
Given this, you can listen for the thisArg of call being evaluate and get a reference to the first argument (InjectedScriptHost)
if (window.URL) {
var ish, _call = Function.prototype.call;
Function.prototype.call = function () { //Could be wrapped in a setter for _commandLineAPI, to redefine only when the user started typing.
if (arguments.length > 0 && this.name === "evaluate" && arguments [0].constructor.name === "InjectedScriptHost") { //If thisArg is the evaluate function and the arg0 is the ISH
ish = arguments[0];
ish.evaluate = function (e) { //Redefine the evaluation behaviour
throw new Error ('Rejected evaluation of: \n\'' + e.split ('\n').slice(1,-1).join ("\n") + '\'');
};
Function.prototype.call = _call; //Reset the Function.prototype.call
return _call.apply(this, arguments);
}
};
}
You could e.g. throw an error, that the evaluation was rejected.
Here is an example where the entered expression gets passed to a CoffeeScript compiler before passing it to the evaluate function.
Netflix also implements this feature
(function() {
try {
var $_console$$ = console;
Object.defineProperty(window, "console", {
get: function() {
if ($_console$$._commandLineAPI)
throw "Sorry, for security reasons, the script console is deactivated on netflix.com";
return $_console$$
},
set: function($val$$) {
$_console$$ = $val$$
}
})
} catch ($ignore$$) {
}
})();
They just override console._commandLineAPI to throw security error.
This is actually possible since Facebook was able to do it.
Well, not the actual web developer tools but the execution of Javascript in console.
See this: How does Facebook disable the browser's integrated Developer Tools?
This really wont do much though since there are other ways to bypass this type of client-side security.
When you say it is client-side, it happens outside the control of the server, so there is not much you can do about it. If you are asking why Facebook still does this, this is not really for security but to protect normal users that do not know javascript from running code (that they don't know how to read) into the console. This is common for sites that promise auto-liker service or other Facebook functionality bots after you do what they ask you to do, where in most cases, they give you a snip of javascript to run in console.
If you don't have as much users as Facebook, then I don't think there's any need to do what Facebook is doing.
Even if you disable Javascript in console, running javascript via address bar is still possible.
and if the browser disables javascript at address bar, (When you paste code to the address bar in Google Chrome, it deletes the phrase 'javascript:') pasting javascript into one of the links via inspect element is still possible.
Inspect the anchor:
Paste code in href:
Bottom line is server-side validation and security should be first, then do client-side after.
Chrome changed a lot since the times facebook could disable console...
As per March 2017 this doesn't work anymore.
Best you can do is disable some of the console functions, example:
if(!window.console) window.console = {};
var methods = ["log", "debug", "warn", "info", "dir", "dirxml", "trace", "profile"];
for(var i=0;i<methods.length;i++){
console[methods[i]] = function(){};
}
My simple way, but it can help for further variations on this subject.
List all methods and alter them to useless.
Object.getOwnPropertyNames(console).filter(function(property) {
return typeof console[property] == 'function';
}).forEach(function (verb) {
console[verb] =function(){return 'Sorry, for security reasons...';};
});
However, a better approach is to disable the developer tool from being opened in any meaningful way
(function() {
'use strict';
Object.getOwnPropertyNames(console).filter(function(property) {
return typeof console[property] == 'function';
}).forEach(function (verb) {
console[verb] =function(){return 'Sorry, for security reasons...';};
});
window.addEventListener('devtools-opened', ()=>{
// do some extra code if needed or ...
// maybe even delete the page, I still like to add redirect just in case
window.location.href+="#";
window.document.head.innerHTML="";
window.document.body.innerHTML="devtools, page is now cleared";
});
window.addEventListener('devtools-closed', ()=>{
// do some extra code if needed
});
let verifyConsole = () => {
var before = new Date().getTime();
debugger;
var after = new Date().getTime();
if (after - before > 100) { // user had to resume the script manually via opened dev tools
window.dispatchEvent(new Event('devtools-opened'));
}else{
window.dispatchEvent(new Event('devtools-closed'));
}
setTimeout(verifyConsole, 100);
}
verifyConsole();
})();
Internally devtools injects an IIFE named getCompletions into the page, called when a key is pressed inside the Devtools console.
Looking at the source of that function, it uses a few global functions which can be overwritten.
By using the Error constructor it's possible to get the call stack, which will include getCompletions when called by Devtools.
Example:
const disableDevtools = callback => {
const original = Object.getPrototypeOf;
Object.getPrototypeOf = (...args) => {
if (Error().stack.includes("getCompletions")) callback();
return original(...args);
};
};
disableDevtools(() => {
console.error("devtools has been disabled");
while (1);
});
an simple solution!
setInterval(()=>console.clear(),1500);
I have a simple way here:
window.console = function () {}
I would go along the way of:
Object.defineProperty(window, 'console', {
get: function() {
},
set: function() {
}
});
In Firefox it dosen't do that, since Firefox is a developer browser, I think since the command WEBGL_debug_renderer_info is deprecated in Firefox and will be removed. Please use RENDERER and the error Referrer Policy: Less restricted policies, including ‘no-referrer-when-downgrade’, ‘origin-when-cross-origin’ and ‘unsafe-url’, will be ignored soon for the cross-site request: https://static.xx.fbcdn.net/rsrc.php/v3/yS/r/XDDAHSZfaR6.js?_nc_x=Ij3Wp8lg5Kz.
This is not a security measure for weak code to be left unattended. Always get a permanent solution to weak code and secure your websites properly before implementing this strategy
The best tool by far according to my knowledge would be to add multiple javascript files that simply changes the integrity of the page back to normal by refreshing or replacing content. Disabling this developer tool would not be the greatest idea since bypassing is always in question since the code is part of the browser and not a server rendering, thus it could be cracked.
Should you have js file one checking for <element> changes on important elements and js file two and js file three checking that this file exists per period you will have full integrity restore on the page within the period.
Lets take an example of the 4 files and show you what I mean.
index.html
<!DOCTYPE html>
<html>
<head id="mainhead">
<script src="ks.js" id="ksjs"></script>
<script src="mainfile.js" id="mainjs"></script>
<link rel="stylesheet" href="style.css" id="style">
<meta id="meta1" name="description" content="Proper mitigation against script kiddies via Javascript" >
</head>
<body>
<h1 id="heading" name="dontdel" value="2">Delete this from console and it will refresh. If you change the name attribute in this it will also refresh. This is mitigating an attack on attribute change via console to exploit vulnerabilities. You can even try and change the value attribute from 2 to anything you like. If This script says it is 2 it should be 2 or it will refresh. </h1>
<h3>Deleting this wont refresh the page due to it having no integrity check on it</h3>
<p>You can also add this type of error checking on meta tags and add one script out of the head tag to check for changes in the head tag. You can add many js files to ensure an attacker cannot delete all in the second it takes to refresh. Be creative and make this your own as your website needs it.
</p>
<p>This is not the end of it since we can still enter any tag to load anything from everywhere (Dependent on headers etc) but we want to prevent the important ones like an override in meta tags that load headers. The console is designed to edit html but that could add potential html that is dangerous. You should not be able to enter any meta tags into this document unless it is as specified by the ks.js file as permissable. <br>This is not only possible with meta tags but you can do this for important tags like input and script. This is not a replacement for headers!!! Add your headers aswell and protect them with this method.</p>
</body>
<script src="ps.js" id="psjs"></script>
</html>
mainfile.js
setInterval(function() {
// check for existence of other scripts. This part will go in all other files to check for this file aswell.
var ksExists = document.getElementById("ksjs");
if(ksExists) {
}else{ location.reload();};
var psExists = document.getElementById("psjs");
if(psExists) {
}else{ location.reload();};
var styleExists = document.getElementById("style");
if(styleExists) {
}else{ location.reload();};
}, 1 * 1000); // 1 * 1000 milsec
ps.js
/*This script checks if mainjs exists as an element. If main js is not existent as an id in the html file reload!You can add this to all js files to ensure that your page integrity is perfect every second. If the page integrity is bad it reloads the page automatically and the process is restarted. This will blind an attacker as he has one second to disable every javascript file in your system which is impossible.
*/
setInterval(function() {
// check for existence of other scripts. This part will go in all other files to check for this file aswell.
var mainExists = document.getElementById("mainjs");
if(mainExists) {
}else{ location.reload();};
//check that heading with id exists and name tag is dontdel.
var headingExists = document.getElementById("heading");
if(headingExists) {
}else{ location.reload();};
var integrityHeading = headingExists.getAttribute('name');
if(integrityHeading == 'dontdel') {
}else{ location.reload();};
var integrity2Heading = headingExists.getAttribute('value');
if(integrity2Heading == '2') {
}else{ location.reload();};
//check that all meta tags stay there
var meta1Exists = document.getElementById("meta1");
if(meta1Exists) {
}else{ location.reload();};
var headExists = document.getElementById("mainhead");
if(headExists) {
}else{ location.reload();};
}, 1 * 1000); // 1 * 1000 milsec
ks.js
/*This script checks if mainjs exists as an element. If main js is not existent as an id in the html file reload! You can add this to all js files to ensure that your page integrity is perfect every second. If the page integrity is bad it reloads the page automatically and the process is restarted. This will blind an attacker as he has one second to disable every javascript file in your system which is impossible.
*/
setInterval(function() {
// check for existence of other scripts. This part will go in all other files to check for this file aswell.
var mainExists = document.getElementById("mainjs");
if(mainExists) {
}else{ location.reload();};
//Check meta tag 1 for content changes. meta1 will always be 0. This you do for each meta on the page to ensure content credibility. No one will change a meta and get away with it. Addition of a meta in spot 10, say a meta after the id="meta10" should also be covered as below.
var x = document.getElementsByTagName("meta")[0];
var p = x.getAttribute("name");
var s = x.getAttribute("content");
if (p != 'description') {
location.reload();
}
if ( s != 'Proper mitigation against script kiddies via Javascript') {
location.reload();
}
// This will prevent a meta tag after this meta tag # id="meta1". This prevents new meta tags from being added to your pages. This can be used for scripts or any tag you feel is needed to do integrity check on like inputs and scripts. (Yet again. It is not a replacement for headers to be added. Add your headers aswell!)
var lastMeta = document.getElementsByTagName("meta")[1];
if (lastMeta) {
location.reload();
}
}, 1 * 1000); // 1 * 1000 milsec
style.css
Now this is just to show it works on all files and tags aswell
#heading {
background-color:red;
}
If you put all these files together and build the example you will see the function of this measure. This will prevent some unforseen injections should you implement it correctly on all important elements in your index file especially when working with PHP.
Why I chose reload instead of change back to normal value per attribute is the fact that some attackers could have another part of the website already configured and ready and it lessens code amount. The reload will remove all the attacker's hard work and he will probably go play somewhere easier.
Another note: This could become a lot of code so keep it clean and make sure to add definitions to where they belong to make edits easy in future. Also set the seconds to your preferred amount as 1 second intervals on large pages could have drastic effects on older computers your visitors might be using
I am pulling my hairs.
I have ZK grid then within the grid there's another grid.
Both are bound to separate view models.
Think about it as a social network wall.
Outer Grid is a ViewModel that render posts.
Then for each post an inner grid is used which is bound to another ViewModel to render comments.
Okay, the issue is "Failed to process setAttr Cannot call method 'set' of null (TypeError)"
HOW TO DEBUG THIS ERROR. No server side error at all. By the way code works fine but every now and then I start get this error.
I am using ZK 6.5.1.1 the latest version.
Note: I know without code it would harder to analyse the problem. But it's not too simple for me to post a portion of working or useful code snippet. So I would appreciate if someone knows how to debug this dreaded message. Also I see other type of similar messages: Failed to mount: cannot call replaceWidget of null etc etc.
Thanks
Regarding to debug this kind of issue, you can try something like below:
.1. Open the debug mode (see ref)
zk.xml
<zk>
<client-config>
<debug-js>true</debug-js>
</client-config>
<library-property>
<name>org.zkoss.web.classWebResource.cache</name>
<value>false</value>
</library-property>
</zk>
.2. Try reproduce this issue, here I create a sample to reproduce a similar issue by unbind a component manually as below (click 'test' button to see the similar error)
test.zul
<zk>
<textbox id="tbx" />
<button label="test">
<attribute name="onClick"><![CDATA[
String uuid = tbx.getUuid();
Clients.evalJavaScript("zk.Widget.$('$tbx').unbind();");
tbx.setValue("abc");
]]></attribute>
</button>
</zk>
.3. See the error message in chrome's developer tooles then click the source link:
.4. Left click on the first line under setAttr to add a breakpoint.
.5. Refersh page and click the 'test' button again, we can see the 'wgt' is null at right side, wgt usually denotes a widget (the Component at client side).
.6. Now what we know is a widget becomes null and then ZK executing setAttr command of it, to debug this, we can simply log every uuid and className while bind_ is called (bind_ is a function of widget's life cycle, basically instanciate all dom elements of a widget) by Client Side Programming, and log all widget again while button clicked.
e.g.,
test.zul (updated)
<zk>
<script><![CDATA[
var allUuids = [];
zk.afterLoad("zul", function () {
var _wgt = {};
// override zk.Widget,
// basically zk.Widget is the
// root of all widget classes
zk.override(zk.Widget.prototype, _wgt, {
bind_: function (a, b, c) {
// call original function
_wgt.bind_.apply(this, arguments);
// each widget has a uuid and className
allUuids.push({uuid: this.uuid, ele: this.className});
}
});
});
function showAllUuids () {
var info,
wgt;
for (var i = 0; i < allUuids.length; i++) {
info = allUuids[i];
// get widget by uuid
wgt = zk.Widget.$('#'+info.uuid);
// show the old className and current status
// you can also try record some more information as needed
// e.g., parent, previousSibling, sclass, etc
zk.log(info.uuid + ' was ' + info.ele + ' now ' + (wgt? wgt.className : wgt));
}
}
]]></script>
<textbox id="tbx" />
<button label="test">
<attribute name="onClick"><![CDATA[
String uuid = tbx.getUuid();
Clients.evalJavaScript("zk.Widget.$('$tbx').unbind();");
tbx.setValue("abc");
Clients.evalJavaScript("showAllUuids();");
]]></attribute>
</button>
</zk>
.7. Now we will get the log message below with the updated zul page after 'test' button clicked and let us know a textbox widget becoms null at client side, you can also check the response value in Network of chromes developer tooles.
Hope this helps
References :
ZK Client Side Programming
Open the debug mode
bind_ in zk.Widget
This particular error seems due to updating a component that is already detached/removed from ZK desktop. In other words, on server side you have a reference to a component that is cached but no longer attached to the component tree. When you try to update it ZK might try to sync its status with its corresponding Widget on client side. However since it was detached, it no longer exists in client side so calling a setAttr on a null widget gives you this error.
Although the best answer possible is already provided I wanted to add I was hitting this error and after debugging it turned out that there was a hflex="min" in a grid component. I changed this to hflex="1" and the error went away. This error started after updating zk version several versions at once so I'm not sure between which versions this change occurred but was a hard to identify. Hopefully simply searching your code base for hflex="min" might save someone some time... I would assume the same to be true for vertical flex.
It come when we are setting something to a already element which is already set previously..
like
OFCchart chart = new OFCchart;
chart.setJSONScript("somedata");
//----- Some other place setting to the same---
chart.setJSONScript("somedata");