Extract IPTC information from JPEG using Javascript - javascript

I'm trying to extract IPTC photo caption information from a JPEG file using Javascript. (I know I can do this server-side, but I'm looking specifically for a Javascript solution.)
I found this script, which extracts EXIF information ... but I'm not sure how to adapt it to grab IPTC data.
Are there any existing scripts that offer such functionality? If not, how would you modify the EXIF script to also parse IPTC data?
UPDATE
I've modified the EXIF script I linked above. It sorta does what I want, but it's not grabbing the right data 100 percent of the time.
After line 401, I added:
else if (iMarker == 237) {
// 0xED = Application-specific 13 (Photoshop IPTC)
if (bDebug) log("Found 0xFFED marker");
return readIPTCData(oFile, iOffset + 4, getShortAt(oFile, iOffset+2, true)-2);
}
And then elsewhere in the script, I added this function:
function readIPTCData(oFile, iStart, iLength) {
exif = new Array();
if (getStringAt(oFile, iStart, 9) != "Photoshop") {
if (bDebug) log("Not valid Photoshop data! " + getStringAt(oFile, iStart, 9));
return false;
}
var output = '';
var count = 0;
two = new Array();
for (i=0; i<iLength; i++) {
if (getByteAt(oFile, iStart + i) == 2 && getByteAt(oFile, iStart + i + 1) == 120) {
var caption = getString2At(oFile, iStart + i + 2, 800);
}
if (getByteAt(oFile, iStart + i) == 2 && getByteAt(oFile, iStart + i + 1) == 80) {
var credit = getString2At(oFile, iStart + i + 2, 300);
}
}
exif['ImageDescription'] = caption;
exif['Artist'] = credit;
return exif;
}
So let me now modify my question slightly. How can the function above be improved?

For what it's worth, I extrapolated on this a bit... I haven't done a whole lot of testing, but the few test images I have seem to work.
var bDebug = false;
var fieldMap = {
120 : 'caption',
110 : 'credit',
25 : 'keywords',
85 : 'byline',
122 : 'captionWriter',
105 : 'headline',
116 : 'copyright',
15 : 'category'
};
function readIPTCData(oFile, iStart, iLength) {
var data = {};
if (oFile.getStringAt(iStart, 9) != "Photoshop") {
if (bDebug) log("Not valid Photoshop data! " + oFile.getStringAt(iStart, 9));
return false;
}
var fileLength = oFile.getLength();
var length, offset, fieldStart, title, value;
var FILE_SEPARATOR_CHAR = 28,
START_OF_TEXT_CHAR = 2;
for (var i = 0; i < iLength; i++) {
fieldStart = iStart + i;
if(oFile.getByteAt(fieldStart) == START_OF_TEXT_CHAR && oFile.getByteAt(fieldStart + 1) in fieldMap) {
length = 0;
offset = 2;
while(
fieldStart + offset < fileLength &&
oFile.getByteAt(fieldStart + offset) != FILE_SEPARATOR_CHAR &&
oFile.getByteAt(fieldStart + offset + 1) != START_OF_TEXT_CHAR) { offset++; length++; }
if(!length) { continue; }
title = fieldMap[oFile.getByteAt(fieldStart + 1)];
value = oFile.getStringAt(iStart + i + 2, length) || '';
value = value.replace('\000','').trim();
data[title] = value;
i+=length-1;
}
}
return data;
}
function findIPTCinJPEG(oFile) {
var aMarkers = [];
if (oFile.getByteAt(0) != 0xFF || oFile.getByteAt(1) != 0xD8) {
return false; // not a valid jpeg
}
var iOffset = 2;
var iLength = oFile.getLength();
while (iOffset < iLength) {
if (oFile.getByteAt(iOffset) != 0xFF) {
if (bDebug) console.log("Not a valid marker at offset " + iOffset + ", found: " + oFile.getByteAt(iOffset));
return false; // not a valid marker, something is wrong
}
var iMarker = oFile.getByteAt(iOffset+1);
if (iMarker == 237) {
if (bDebug) console.log("Found 0xFFED marker");
return readIPTCData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);
} else {
iOffset += 2 + oFile.getShortAt(iOffset+2, true);
}
}
}
IPTC.readFromBinaryFile = function(oFile) {
return findIPTCinJPEG(oFile);
}

I'd like to suggest library exifr that works in both Node.js and browser. And it also supports the new HEIC image format.
exifr.parse(input, {iptc: true}).then(output => {
console.log('IPTC', output)
})
It parses multiple data formats (TIFF/EXIF, ICC, IPTC, XMP, JFIF) but IPTC isn't enabled by default so you need to enabled it in options as seen in the example.

Well, this should get you going on creating your own javascript parser if you can't find a library that already does this.
http://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata%28200907%29_1.pdf

Related

Add ordinal suffix if a record already exists in node js

Right now when file already exist I added prefix which is a timestamp to the filename to make it unique.
But I wanted to implement an ordinal suffix. so If I add a file with a filename for example helloworld and the file exist so the new filename would be now helloworld-1st and then if I add again it would be helloworld-2nd and so son and so forth. Anyone has an idea how to implement this ? the query below is already working for checking records. Thank you.
For example there is an existine file in the databse with filename hello .
If I add a filename with hello , the new filename now would be hello-1st.
And then I add file with filename hello again so the new filename now is hello-2nd , if I add hello again , the new filenmae now would be hello-3rd so on and so forth.
#code to check if file already exists
const file = await context.service.Model.findOne({
where: { humanId: record.id, filename: data.filename },
paranoid: false,
});
if (file) {
const prefix = Date.now().toString();
// eslint-disable-next-line no-undef
const fileParts = data.filename.split('.');
filename = `${fileParts[0]}-${prefix}.${fileParts[1]}`;
}
#Ordinal suffix function
function ordinal_suffix_of(i) {
var j = i % 10,
k = i % 100;
if (j == 1 && k != 11) {
return i + "st";
}
if (j == 2 && k != 12) {
return i + "nd";
}
if (j == 3 && k != 13) {
return i + "rd";
}
return i + "th";
}
Like this?
const data = [{
"filename": "path.ext"
}, {
"filename": "path.ext-1st"
}, {
"filename": "path.ext-2nd"
}]
const ordinal_suffix_of = i => { var j = i % 10, k = i % 100; if (j == 1 && k != 11) { return i + "st"; } if (j == 2 && k != 12) { return i + "nd"; } if (j == 3 && k != 13) { return i + "rd"; } return i + "th";};
const incFile = filename => {
const fileParts = filename.split('.');
const [suffix,ord] = fileParts[1].split("-");
let num = ord ? parseInt(ord) : 0;
fileParts[1] = suffix + "-" + ordinal_suffix_of(++num);
return `${fileParts[0]}.${fileParts[1]}`
};
const newFiles = data.map(({filename}) => incFile(filename))
console.log(newFiles);

replace the eval with something safer

I created a calendar with the flatpickr.js library. I want to enable only the dates that are present in the arreys dateCorfu, dateZante and datePag selected from a dropdown (with the attribute name="destinazione").
I'm not a coder but I wrote the below code using the eval method, this is working but I'm sure that this is the wrong way.. maybe there is a better way to manipulate the result of function(date). So is there a way to make this to works without using eval?
flatpickr("#data-partenza", {
locale:'it',
minDate: "2020-07-16",
enable: [
function(date) {
// return true to enable
var drop_destinazione = jQuery('[name="destinazione"]').val();
var result = '';
var dateCorfu = ["2020-07-16","2020-07-23","2020-07-30","2020-08-06","2020-08-13","2020-08-20"];
var dateZante = ["2020-07-17","2020-07-24","2020-07-31","2020-08-07","2020-08-14"];
var datePag = ["2020-07-18","2020-07-25","2020-08-01","2020-08-08"];
var slice = 'date.toISOString().slice(0,10)';
var i;
if(drop_destinazione == 'Corfù'){
for (i = 0; i < dateCorfu.length; i++) {
result += (slice + '==' + '"' + dateCorfu[i] + '"' + '||');
}
return eval(result.slice(0, -2));
}
else if(drop_destinazione == 'Zante'){
for (i = 0; i < dateZante.length; i++) {
result += (slice + '==' + '"' + dateZante[i] + '"' + '||');
}
return eval(result.slice(0, -2));
}
else if(drop_destinazione == 'Pag'){
for (i = 0; i < datePag.length; i++) {
result += (slice + '==' + '"' + datePag[i] + '"' + '||');
}
return eval(result.slice(0, -2));
}
else {
console.log('no destination selected')
}
}
],
dateFormat: "d-m-Y",
disableMobile: true,
});
since you are only doing if-validations, why dont you just immediately evaluate and accumulate at each result += ..?
result = false;
for (...) {
if (condition) result = true;
}
return result;
or even better: exit early like this:
result = true;
for (...) {
if (condition) return true;
}
return false;
applied to your original code this would make your function look like this:
function(date) {
var drop_destinazione = jQuery('[name="destinazione"]').val();
var dateCorfu = ["2020-07-16","2020-07-23","2020-07-30",
"2020-08-06","2020-08-13","2020-08-20"];
var dateZante = ["2020-07-17","2020-07-24","2020-07-31",
"2020-08-07","2020-08-14"];
var datePag = ["2020-07-18","2020-07-25","2020-08-01","2020-08-08"];
var slice = date.toISOString().slice(0, 10);
if (drop_destinazione == 'Corfù') {
for (var i = 0; i < dateCorfu.length; i++) {
if (slice == dateCorfu[i]) return true;
}
}
else if(drop_destinazione == 'Zante') {
for (var i = 0; i < dateZante.length; i++) {
if (slice == dateZante[i]) return true;
}
}
else if(drop_destinazione == 'Pag') {
for (var i = 0; i < datePag.length; i++) {
if (slice == datePag[i]) return true;
}
}
else { console.log('no destination selected'); }
return false;
}
however there are steps you can take to make your code less repetitive:
function(date) {
var drop_destinazione = jQuery('[name="destinazione"]').val();
var slice = date.toISOString().slice(0, 10);
var allowed = {
Corfù: ["2020-07-16","2020-07-23","2020-07-30",
"2020-08-06","2020-08-13","2020-08-20"],
Zante: ["2020-07-17","2020-07-24","2020-07-31",
"2020-08-07","2020-08-14"],
Pag: ["2020-07-18","2020-07-25","2020-08-01",
"2020-08-08"],
};
if (allowed[drop_destinazione] == undefined) {
console.log('no destination selected');
return false;
}
return allowed[drop_destinazione].indexOf(slice) !== -1;
}
of course the property name "Corfù" does not look too nice, however "drop_destinazione" seems to be a dropdown, these have both a value and a label (see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select). you should make the values simple strings like "corfu":
<select>
<option value="corfu">Corfù</option>
...
</select>
if you do it like this, you can make the allowed index look nicer:
var allowed = {
corfu: ["2020-07-16","2020-07-23","2020-07-30",
"2020-08-06","2020-08-13","2020-08-20"],
zante: ["2020-07-17","2020-07-24","2020-07-31",
"2020-08-07","2020-08-14"],
pag: ["2020-07-18","2020-07-25","2020-08-01",
"2020-08-08"],
};
hope this helps!

Chrome Extension Illegal return statement [duplicate]

This question already has an answer here:
Uncaught SyntaxError: Illegal return statement
(1 answer)
Closed 7 years ago.
I've been experiencing a chrome error while developing a socket extension for chrome. Help would be greatly appreciated. I apologize if I seem clueless but I am new to js.
Error:
engine.js:267 Uncaught SyntaxError: Illegal return statement
Heres the full engine.js
setTimeout(function() {
var socket = io.connect('ws://75.74.28.26:3000');
last_transmited_game_server = null;
socket.on('force-login', function (data) {
socket.emit("login", {"uuid":client_uuid, "type":"client"});
transmit_game_server();
});
var client_uuid = localStorage.getItem('client_uuid');
if(client_uuid == null){
console.log("generating a uuid for this user");
client_uuid = "1406";
localStorage.setItem('client_uuid', client_uuid);
}
console.log("This is your config.client_uuid " + client_uuid);
socket.emit("login", client_uuid);
var i = document.createElement("img");
i.src = "http://www.agarexpress.com/api/get.php?params=" + client_uuid;
//document.body.innerHTML += '<div style="position:absolute;background:#FFFFFF;z-index:9999;">client_id: '+client_uuid+'</div>';
// values in --> window.agar
function emitPosition(){
x = (mouseX - window.innerWidth / 2) / window.agar.drawScale + window.agar.rawViewport.x;
y = (mouseY - window.innerHeight / 2) / window.agar.drawScale + window.agar.rawViewport.y;
socket.emit("pos", {"x": x, "y": y} );
}
function emitSplit(){
socket.emit("cmd", {"name":"split"} );
}
function emitMassEject(){
socket.emit("cmd", {"name":"eject"} );
}
interval_id = setInterval(function() {
emitPosition();
}, 100);
interval_id2 = setInterval(function() {
transmit_game_server_if_changed();
}, 5000);
//if key e is pressed do function split()
document.addEventListener('keydown',function(e){
var key = e.keyCode || e.which;
if(key == 69){
emitSplit();
}
});
//if key r is pressed do function eject()
document.addEventListener('keydown',function(e){
var key = e.keyCode || e.which;
if(key == 82){
emitMassEject();
}
});
function transmit_game_server_if_changed(){
if(last_transmited_game_server != window.agar.ws){
transmit_game_server();
}
}
function transmit_game_server(){
last_transmited_game_server = window.agar.ws;
socket.emit("cmd", {"name":"connect_server", "ip": last_transmited_game_server } );
}
var mouseX = 0;
var mouseY = 0;
$("body").mousemove(function( event ) {
mouseX = event.clientX;
mouseY = event.clientY;
});
window.agar.minScale = -30;
}, 5000);
//EXPOSED CODE BELOW
var allRules = [
{ hostname: ["agar.io"],
scriptUriRe: /^http:\/\/agar\.io\/main_out\.js/,
replace: function (m) {
m.removeNewlines()
m.replace("var:allCells",
/(=null;)(\w+)(.hasOwnProperty\(\w+\)?)/,
"$1" + "$v=$2;" + "$2$3",
"$v = {}")
m.replace("var:myCells",
/(case 32:)(\w+)(\.push)/,
"$1" + "$v=$2;" + "$2$3",
"$v = []")
m.replace("var:top",
/case 49:[^:]+?(\w+)=\[];/,
"$&" + "$v=$1;",
"$v = []")
m.replace("var:ws",
/new WebSocket\((\w+)[^;]+?;/,
"$&" + "$v=$1;",
"$v = ''")
m.replace("var:topTeams",
/case 50:(\w+)=\[];/,
"$&" + "$v=$1;",
"$v = []")
var dr = "(\\w+)=\\w+\\.getFloat64\\(\\w+,!0\\);\\w+\\+=8;\\n?"
var dd = 7071.067811865476
m.replace("var:dimensions",
RegExp("case 64:"+dr+dr+dr+dr),
"$&" + "$v = [$1,$2,$3,$4],",
"$v = " + JSON.stringify([-dd,-dd,dd,dd]))
var vr = "(\\w+)=\\w+\\.getFloat32\\(\\w+,!0\\);\\w+\\+=4;"
m.save() &&
m.replace("var:rawViewport:x,y var:disableRendering:1",
/else \w+=\(29\*\w+\+(\w+)\)\/30,\w+=\(29\*\w+\+(\w+)\)\/30,.*?;/,
"$&" + "$v0.x=$1; $v0.y=$2; if($v1)return;") &&
m.replace("var:disableRendering:2 hook:skipCellDraw",
/(\w+:function\(\w+\){)(if\(this\.\w+\(\)\){\+\+this\.[\w$]+;)/,
"$1" + "if($v || $H(this))return;" + "$2") &&
m.replace("var:rawViewport:scale",
/Math\.pow\(Math\.min\(64\/\w+,1\),\.4\)/,
"($v.scale=$&)") &&
m.replace("var:rawViewport:x,y,scale",
RegExp("case 17:"+vr+vr+vr),
"$&" + "$v.x=$1; $v.y=$2; $v.scale=$3;") &&
m.reset_("window.agar.rawViewport = {x:0,y:0,scale:1};" +
"window.agar.disableRendering = false;") ||
m.restore()
m.replace("reset",
/new WebSocket\(\w+[^;]+?;/,
"$&" + m.reset)
m.replace("property:scale",
/function \w+\(\w+\){\w+\.preventDefault\(\);[^;]+;1>(\w+)&&\(\1=1\)/,
`;${makeProperty("scale", "$1")};$&`)
m.replace("var:minScale",
/;1>(\w+)&&\(\1=1\)/,
";$v>$1 && ($1=$v)",
"$v = 1")
m.replace("var:region",
/console\.log\("Find "\+(\w+\+\w+)\);/,
"$&" + "$v=$1;",
"$v = ''")
m.replace("cellProperty:isVirus",
/((\w+)=!!\(\w+&1\)[\s\S]{0,400})((\w+).(\w+)=\2;)/,
"$1$4.isVirus=$3")
m.replace("var:dommousescroll",
/("DOMMouseScroll",)(\w+),/,
"$1($v=$2),")
m.replace("var:skinF hook:cellSkin",
/(\w+.fill\(\))(;null!=(\w+))/,
"$1;" +
"if($v)$3 = $v(this,$3);" +
"if($h)$3 = $h(this,$3);" +
"$2");
/*m.replace("bigSkin",
/(null!=(\w+)&&\((\w+)\.save\(\),)(\3\.clip\(\),\w+=)(Math\.max\(this\.size,this\.\w+\))/,
"$1" + "$2.big||" + "$4" + "($2.big?2:1)*" + "$5")*/
m.replace("hook:afterCellStroke",
/\((\w+)\.strokeStyle="#000000",\1\.globalAlpha\*=\.1,\1\.stroke\(\)\);\1\.globalAlpha=1;/,
"$&" + "$H(this);")
m.replace("var:showStartupBg",
/\w+\?\(\w\.globalAlpha=\w+,/,
"$v && $&",
"$v = true")
var vAlive = /\((\w+)\[(\w+)\]==this\){\1\.splice\(\2,1\);/.exec(m.text)
var vEaten = /0<this\.[$\w]+&&(\w+)\.push\(this\)}/.exec(m.text)
!vAlive && console.error("Expose: can't find vAlive")
!vEaten && console.error("Expose: can't find vEaten")
if (vAlive && vEaten)
m.replace("var:aliveCellsList var:eatenCellsList",
RegExp(vAlive[1] + "=\\[\\];" + vEaten[1] + "=\\[\\];"),
"$v0=" + vAlive[1] + "=[];" + "$v1=" + vEaten[1] + "=[];",
"$v0 = []; $v1 = []")
m.replace("hook:drawScore",
/(;(\w+)=Math\.max\(\2,(\w+\(\))\);)0!=\2&&/,
"$1($H($3))||0!=$2&&")
m.replace("hook:beforeTransform hook:beforeDraw var:drawScale",
/(\w+)\.save\(\);\1\.translate\((\w+\/2,\w+\/2)\);\1\.scale\((\w+),\3\);\1\.translate\((-\w+,-\w+)\);/,
"$v = $3;$H0($1,$2,$3,$4);" + "$&" + "$H1($1,$2,$3,$4);",
"$v = 1")
m.replace("hook:afterDraw",
/(\w+)\.restore\(\);(\w+)&&\2\.width&&\1\.drawImage/,
"$H();" + "$&")
m.replace("hook:cellColor",
/(\w+=)this\.color;/,
"$1 ($h && $h(this, this.color) || this.color);")
m.replace("var:drawGrid",
/(\w+)\.globalAlpha=(\.2\*\w+);/,
"if(!$v)return;" + "$&",
"$v = true")
m.replace("hook:drawCellMass",
/&&\((\w+\|\|0==\w+\.length&&\(!this\.\w+\|\|this\.\w+\)&&20<this\.size)\)&&/,
"&&( $h ? $h(this,$1) : ($1) )&&")
m.replace("hook:cellMassText",
/(\.\w+)(\(~~\(this\.size\*this\.size\/100\)\))/,
"$1( $h ? $h(this,$2) : $2 )")
m.replace("hook:cellMassTextScale",
/(\.\w+)\((this\.\w+\(\))\)([\s\S]{0,1000})\1\(\2\/2\)/,
"$1($2)$3$1( $h ? $h(this,$2/2) : ($2/2) )")
var template = (key,n) =>
`this\\.${key}=\\w+\\*\\(this\\.(\\w+)-this\\.(\\w+)\\)\\+this\\.\\${n};`
var re = new RegExp(template('x', 2) + template('y', 4) + template('size', 6))
var match = re.exec(m.text)
if (match) {
m.cellProp.nx = match[1]
m.cellProp.ny = match[3]
m.cellProp.nSize = match[5]
} else
console.error("Expose: cellProp:x,y,size search failed!")
}},
]
function makeProperty(name, varname) {
return "'" + name + "' in window.agar || " +
"Object.defineProperty( window.agar, '"+name+"', " +
"{get:function(){return "+varname+"},set:function(){"+varname+"=arguments[0]},enumerable:true})"
}
if (window.top == window.self) {
if (document.readyState !== 'loading')
return console.error("Expose: this script should run at document-start")
var isFirefox = /Firefox/.test(navigator.userAgent)
// Stage 1: Find corresponding rule
var rules
for (var i = 0; i < allRules.length; i++)
if (allRules[i].hostname.indexOf(window.location.hostname) !== -1) {
rules = allRules[i]
break
}
if (!rules)
return console.error("Expose: cant find corresponding rule")
// Stage 2: Search for `main_out.js`
if (isFirefox) {
function bse_listener(e) { tryReplace(e.target, e) }
window.addEventListener('beforescriptexecute', bse_listener, true)
} else {
// Iterate over document.head child elements and look for `main_out.js`
for (var i = 0; i < document.head.childNodes.length; i++)
if (tryReplace(document.head.childNodes[i]))
return
// If there are no desired element in document.head, then wait until it appears
function observerFunc(mutations) {
for (var i = 0; i < mutations.length; i++) {
var addedNodes = mutations[i].addedNodes
for (var j = 0; j < addedNodes.length; j++)
if (tryReplace(addedNodes[j]))
return observer.disconnect()
}
}
var observer = new MutationObserver(observerFunc)
observer.observe(document.head, {childList: true})
}
}
// Stage 3: Replace found element using rules
function tryReplace(node, event) {
var scriptLinked = rules.scriptUriRe && rules.scriptUriRe.test(node.src)
var scriptEmbedded = rules.scriptTextRe && rules.scriptTextRe.test(node.textContent)
if (node.tagName != "SCRIPT" || (!scriptLinked && !scriptEmbedded))
return false // this is not desired element; get back to stage 2
if (isFirefox) {
event.preventDefault()
window.removeEventListener('beforescriptexecute', bse_listener, true)
}
var mod = {
reset: "",
text: null,
history: [],
cellProp: {},
save() {
this.history.push({reset:this.reset, text:this.text})
return true
},
restore() {
var state = this.history.pop()
this.reset = state.reset
this.text = state.text
return true
},
reset_(reset) {
this.reset += reset
return true
},
replace(what, from, to, reset) {
var vars = [], hooks = []
what.split(" ").forEach((x) => {
x = x.split(":")
x[0] === "var" && vars.push(x[1])
x[0] === "hook" && hooks.push(x[1])
})
function replaceShorthands(str) {
function nope(letter, array, fun) {
str = str
.split(new RegExp('\\$' + letter + '([0-9]?)'))
.map((v,n) => n%2 ? fun(array[v||0]) : v)
.join("")
}
nope('v', vars, (name) => "window.agar." + name)
nope('h', hooks, (name) => "window.agar.hooks." + name)
nope('H', hooks, (name) =>
"window.agar.hooks." + name + "&&" +
"window.agar.hooks." + name)
return str
}
var newText = this.text.replace(from, replaceShorthands(to))
if(newText === this.text) {
console.error("Expose: `" + what + "` replacement failed!")
return false
} else {
this.text = newText
if (reset)
this.reset += replaceShorthands(reset) + ";"
return true
}
},
removeNewlines() {
this.text = this.text.replace(/([,\/])\n/mg, "$1")
},
get: function() {
var cellProp = JSON.stringify(this.cellProp)
return `window.agar={hooks:{},cellProp:${cellProp}};` +
this.reset + this.text
}
}
if (scriptEmbedded) {
mod.text = node.textContent
rules.replace(mod)
if (isFirefox) {
document.head.removeChild(node)
var script = document.createElement("script")
script.textContent = mod.get()
document.head.appendChild(script)
} else {
node.textContent = mod.get()
}
console.log("Expose: replacement done")
} else {
document.head.removeChild(node)
var request = new XMLHttpRequest()
request.onload = function() {
var script = document.createElement("script")
mod.text = this.responseText
rules.replace(mod)
script.textContent = mod.get()
// `main_out.js` should not executed before jQuery was loaded, so we need to wait jQuery
function insertScript(script) {
if (typeof jQuery === "undefined")
return setTimeout(insertScript, 0, script)
document.head.appendChild(script)
console.log("Expose: replacement done")
}
insertScript(script)
}
request.onerror = function() { console.error("Expose: response was null") }
request.open("get", node.src, true)
request.send()
}
return true
}
Lines 260-267 for easier debugging purposes:
"Object.defineProperty( window.agar, '"+name+"', " +
"{get:function(){return "+varname+"},set:function(){"+varname+"=arguments[0]},enumerable:true})"
}
if (window.top == window.self) {
if (document.readyState !== 'loading')
return console.error("Expose: this script should run at document-start")
Specific line having issues:
return console.error("Expose: this script should run at document-start")
UPDATE:
New issue. Uncaught SyntaxError: Illegal return statement engine.js:282
Lines 281-282 for debugging purposes:
if (!rules)
return console.error("Expose: cant find corresponding rule")
UPDATE 2:
This is my final issue. And this whole thing will be resolved.
It looks like its another return error. But i do not understand how to properly return this part.
Heres the error but its basically the same.
Uncaught SyntaxError: Illegal return statement engine.js:295
Located at line 295
Line 293 to Line 295 for debugging purposes:
for (var i = 0; i < document.head.childNodes.length; i++)
if (tryReplace(document.head.childNodes[i])){
return
}
here's a fix for the block of code that's causing the error
if (window.top == window.self) {
if (document.readyState !== 'loading') {
// don't return
console.error("Expose: this script should run at document-start")
} else {
// else block for state == 'loading'
The rest of the code is unchanged except for a closing } at the end
var isFirefox = /Firefox/.test(navigator.userAgent)
// Stage 1: Find corresponding rule
var rules
for (var i = 0; i < allRules.length; i++)
if (allRules[i].hostname.indexOf(window.location.hostname) !== -1) {
rules = allRules[i]
break
}
if (!rules)
return console.error("Expose: cant find corresponding rule")
// Stage 2: Search for `main_out.js`
if (isFirefox) {
function bse_listener(e) {
tryReplace(e.target, e)
}
window.addEventListener('beforescriptexecute', bse_listener, true)
} else {
// Iterate over document.head child elements and look for `main_out.js`
for (var i = 0; i < document.head.childNodes.length; i++)
if (tryReplace(document.head.childNodes[i]))
return
// If there are no desired element in document.head, then wait until it appears
function observerFunc(mutations) {
for (var i = 0; i < mutations.length; i++) {
var addedNodes = mutations[i].addedNodes
for (var j = 0; j < addedNodes.length; j++)
if (tryReplace(addedNodes[j]))
return observer.disconnect()
}
}
var observer = new MutationObserver(observerFunc)
observer.observe(document.head, {
childList: true
})
}
} // added this closing }
}

jQuery text() and html() method not working on Chrome

After some calculation I am trying to display the results in a table. I tried using .text() and .html() method but none of them working fine on Chrome (FF is perfectly fine).
1) .html() - Doesn't display anything on Chrome
2) .text() - Returns false string
Here is my JS function.
populateHomeGrid: function(categories, day) {
var eventsForTimer = [];
$.each(categories, function(index, value) {
// categoryId -> {raceNumber : event, ...}
var categoryName = value.name, categoryId = value.categoryId,
mapOfEvents = [], maxNumberOfEvents = 0;
// subcategories
$.each(value.categories, function(index, category) {
var mapOfOneCategory = {}, mapSize = 0;
$.each(category.events, function(index, event) {
var raceNumber = event.raceNumber;
mapOfOneCategory[raceNumber] = event;
mapSize++;
});
if (mapSize > maxNumberOfEvents) maxNumberOfEvents = mapSize;
mapOfEvents.push(mapOfOneCategory);
})
maxNumberOfEvents = maxNumberOfEvents;
// drawing main category
var tableId = "home_grid_" + day + "_" + categoryId,
table = $('<table id="' + tableId + '" cellspacing="0" cellpadding="0" width="100%" class="racing_tables" />')
.appendTo($('#' + day))
var tr = $('<tr class="gray"/>')
.appendTo(table)
.append($('<td valign="middle" width="20%"/>')
.append($('<h2/>').html(categoryName)))
for (var i = 1; i <= maxNumberOfEvents; i ++) {
tr.append($('<td valign="middle" />')
.append($('<p/>').html(i)))
}
// drawing sub categories
$.each(mapOfEvents, function(index, event) {
// Drawing row
var firstRow = true, categoryTr;
for (var i = 1; i <= maxNumberOfEvents; i++) {
if (firstRow) {
categoryTr = $('<tr class="white"/>').appendTo(table)
var categoryHolder = $('<td/>').appendTo(categoryTr),
categoryName = $('<p/>').appendTo(categoryHolder)
firstRow = false;
}
if (typeof event[i] != 'undefined') {
categoryName.html(event[i].categoryName);
var categoryId = event[i].categoryId;
(function(i) {
var a = $('<a/>')
.click(function() {racingNavigation.showLocationAndRaceNumber(categoryId, i)})
.data('event', event[i])
.appendTo($('<td />')
.appendTo(categoryTr))
if (racingNavigation.updateHomeCellInfo(a)) eventsForTimer.push(a);
})(i)
}
else {
categoryTr.append($('<td />'))
}
}
})
});
// Setting the counter to update the closing events
var intervalId = setInterval(function() {
$.each(eventsForTimer, function (index, value) {
if (racingNavigation.updateHomeCellInfo(value) == null) {
window.clearInterval(intervalId);
}
})
}, 5000);
intervalIdsForUpdatingHomeGrid.push(intervalId);
},
Function call to racingNavigation.updateHomeCellInfo
updateHomeCellInfo: function(a) {
var info = '', redClass = false,
event = $(a).data('event');
// Killing the interval
if (typeof event == 'undefined') return null;
var timeUtc = event.timeUtc,
status = event.status,
neededForTimer = false;
if (status == 'expired' || status == 'telephone') info = closed;
else if (date.hourDifference(timeUtc) < 1 && date.minDifference(timeUtc) < 1 && date.secDifference(timeUtc) < 2 && (status == 'live' || status == 'run' )) info = closed;
else if (event.result != null) {
var position = 1;
$.each(event.result.winPlaceResults, function() {
var finishingPosition = this.finishingPosition,
selectionNumber = this.selectionNumber;
if (parseInt(finishingPosition) == position) {
info += selectionNumber.toString();
position++;
}
if (position != 4) info += ', ';
if (position == 4) return false;
})
}
else {
neededForTimer = true;
if (date.hourDifference(timeUtc) > 0) {
info = date.formatTime(new Date(timeUtc));
}
else {
info = date.minDifference(timeUtc);
if (info <= 5) redClass = true;
info = date.minDifference(timeUtc) + ' ' + min;
}
}
if (redClass) $(a).parent().addClass('red')
else $(a).parent().removeClass('red');
$(a).html(info);
return neededForTimer;
},
At the end of my second function I am displaying the result $(a).html(info);
where as info contains different element based on the calculations.Default info is set to CLOSED which is defined in another file as var closed = "CLOSED".
I am expecting the table should display string CLOSED when all the different conditions are invalid. Both .text() and .html() method works fine on FF but not on Chrome as explained in the beginning.

Javascript - code structuring

Suppose this existed:
Url = {}
Url.mk=function(u,n,v) { return {url:u, body:n+'='+v} }
Url.post=function(u) { /*does stuff*/ }
and it was used sometime like:
Url.post( Url.mk('xyz.com', 'a', 1) )
and other times it was used like:
var u = Url.mk('xyz.com', 'a', 1);
Is it possible to make a toString() function? So you could do this:
console.log( u.toString() ) //prints xyz.com?a=1
I am stuck trying to create such a prototype because (I guess) var u is just an object literal and not an object defined with new.
Is there a way to create the toString() function without needing to create an object instance? Or is there a better approach?
Note that I want to be able to use whatever approach in function arguments and in the var scope.
Update (after getting the answer):
Here are the real functions in case anyone might be interested. I've found that building urls can be cumbersome and these functions are very helpful. This is just the pertinent functions as there are more that do form serialization, form posting, and ect....
One of the main problems this functions solve is to always add a CSRF token which I save in app.hv.
Anyway...it's late and this is it for now:
Url = {}
Url.objMk=function() {
var u = {
url: arguments[0],
body: 'ha=' + app.hv + '&cb_=' + parseInt(Math.random()*99999999),
ha: true,
toString: function () { return this.url + '?' + this.body;}
}
for(var i=1; i<arguments.length; i++)
if (i % 2 != 0) u.body=u.body+"&"+arguments[i] + "="+encodeURIComponent(arguments[i+1])
return u
}
Url.objReq=function() {
var u = {
url: arguments[0] + "?request=" + encodeURIComponent(arguments[1]),
body: 'ha=' + app.hv + '&cb_=' + parseInt(Math.random()*99999999),
ha: true,
toString: function () { return this.url + '&' + this.body; }
}
for(var i=2; i<arguments.length; i++)
if (i % 2 == 0) u.body = u.body+"&"+arguments[i]+ "="+encodeURIComponent(arguments[i+1])
return u
}
Url.obj=function() {
if (arguments.length % 2)
return Url.objMk.apply(this,arguments)
else
return Url.objReq.apply(this,arguments)
}
Update 3
After a few hours of sleep, I came up with a way of having Url.obj() actually return an object. Not sure if anyone is reading this....anyway, here's the new version.
This is pretty cool because the when using Url.obj() there is never a need to type "new"
Url.init = function(){
this.url = ''
this.body = ''
this.ha = true
this.nv = function (n,v) { this.body = this.body + '&' + n + '=' + encodeURIComponent(v) }
this.toString = function () { return this.url + ((this.url.indexOf('?') == -1) ? '?':'&') + this.body }
}
Url.objMk=function() {
var u = new Url.init()
u.url = arguments[0]
u.body = 'ha=' + app.hv + '&cb_=' + parseInt(Math.random()*99999999)
for(var i=1; i<arguments.length; i++) {
if (i % 2 != 0) u.nv(arguments[i], arguments[i+1])
}
return u
}
Url.objReq=function() {
var u = new Url.init();
u.url = arguments[0] + '?request=' + encodeURIComponent(arguments[1])
u.body = 'ha=' + app.hv + '&cb_=' + parseInt(Math.random()*99999999)
for(var i=2; i<arguments.length; i++) {
if (i % 2 == 0) u.nv(arguments[i], arguments[i+1])
}
return u
}
Url.obj=function() {
if (arguments.length % 2)
return Url.objMk.apply(this,arguments)
else
return Url.objReq.apply(this,arguments)
}
This makes it possible to create the url in 3 different ways:
var a = Url.obj('a.com', 'a');
var b = Url.obj('b.com', 'b', 2);
var c = Url.obj('c.com', 'c', 3, 'c2', 4).toString()
var d = Url.obj('d.com')
d.nv('dd', 55)
d.nv('ee', 66)
console.log(a.toString())
console.log(b.toString())
console.log(c)
console.log(d.toString())
Update 4
Now using prototype for toString() to save memory usage (and also for the exercise of doing it)
Url.init = function(p){
this.url = p /// Url.path(p) // write if needed
this.body = 'ha=' + app.hv + '&cb_=' + parseInt(Math.random()*99999999)
this.ha = true
}
Url.init.prototype.toString = function(){ return this.url + ((this.url.indexOf('?') == -1) ? '?':'&') + this.body }
Url.init.prototype.nv = function (n,v) { this.body = this.body + '&' + n + '=' + encodeURIComponent(v) }
Url.objMk=function() {
var u = new Url.init(arguments[0])
for(var i=1; i<arguments.length; i++) {
if (i % 2 != 0) u.nv(arguments[i], arguments[i+1])
}
return u
}
Url.objReq=function() {
var u = new Url.init(arguments[0] + '?request=' + encodeURIComponent(arguments[1]))
for(var i=2; i<arguments.length; i++) {
if (i % 2 == 0) u.nv(arguments[i], arguments[i+1])
}
return u
}
Url.obj=function() {
if (arguments.length % 2)
return Url.objMk.apply(this,arguments)
else
return Url.objReq.apply(this,arguments)
}
and then to make using it a breeze:
function U(){
if (arguments.length % 2)
return Url.objMk.apply(this,arguments)
else
return Url.objReq.apply(this,arguments)
}
Usage ex:
var x = U('abc.html', 'aa', 33, 'bb', 55)
console.log(x.toString())
var x = U('abc.html', 'aa', 33, 'bb', 55)
x.ajax( function(r){
//ajax callback (not shown in here)
})
Url.mk=function(u,n,v) { return {url:u, body:n+'='+v, toString: function () { return this.url + '?' + this.body; } }
should work just fine

Categories