Javascript: override native DOM method - javascript

I would like to make my website(actually a web app) packaged into single file. I know a easiest way is to replace all path/url inside my code into data-url. But it will make the file hard to read by human. My idea is to use an array to store all data-url and write a function to obtain them by original url(as query string). It can also return the original url if nothing found.
Example:
store = new Array();
store.push({"url":"/img/icon.png","data-url":"dataurl:XXXXX"});
store.push({"url":"/img/icon1.png","data-url":"dataurl:XXXXX"});
function getResource(url) {
var result = url;
for(var row in store){
if (row.url == url) {
result = row.data-url;
}
}
return result;
}
So to use it, you also need a method to change the attribute in HTML element:
function replaceResource(e,attbName) {
e.target.setAttribute(attbName,getResource(e.target.getAttribute(attbName));
}
And in HTML:
<img src="/img/icon.png" onload="replaceResource(event,'src');" />
But I want to be simpler(since it's not good for human to read also). I want to override the DOM method for each type of HTMLElement(img,script etc.) by something like:
HTMLImageElement.prototype.src.callback = function (event) {
e.target.src = getResource(e.target.src);
}
So you don't need to do anything in HTML:
<img src="/img/icon.png" />
However the code for overriding native DOM method above is only my day-dream. I don't know what is correct syntax :'( Anybody can help?
Here is a reference to ADD custom method to native DOM element:
http://www.meekostuff.net/blog/Overriding-DOM-Methods/

Related

How to save strings to SPECIFIC location in p5.js

Here I have a code that I was playing around with.
It loads a string within my file and saves an unimportant one.
var file = "1";
var result;
var meString;
var splitMeString;
function preload() {
result = loadStrings("assets/save/"+file+".txt");
}
function setup() {
createCanvas(1000,650);
}
function draw() {
meString = result+'';
splitMeString = splitTokens(meString, ',');
text(meString,20,20);
console.log(splitMeString[2]);
}
function mousePressed(){
saveStrings("happy");
}
but how would I save a string to a specific location? Say I wanted to overwrite the file ("file")?
Questions like these are best answered by looking in the reference.
According to the reference, the saveStrings() function can take three arguments:
Syntax
saveStrings(list,filename,[extension])
Parameters
list String[]: string array to be written
filename String: filename for output
extension String: the filename's extension
So it sounds like you're looking for something like this:
saveStrings(yourArray, "file", "txt");
Also note that the third argument is optional, so this should also work:
saveStrings(yourArray, "file");
If you use the functions storeItem() and getItem() you can save strings to your program, this won't save it to a specific file embedded in your code but it will save it to your code. You can call whatever you stored in storeItem() with getItem()even after you close out of the tab. If you need any more info on it you can find it on the reference page here.
Hope this helps!

How to retrieve hotspot from KRPANO using Javascript

I wan't to retrieve a hotspot from KRPANO using a javascript call.
With the below content I retrieve undefined.
KRPANO XML snippet:
<hotspot name="spot0" style="hotspot_ani_white" ath="-25" atv="-10" />
<hotspot name="spot1" style="hotspot_ani_white" ath="-25" atv="-10" />
External javascript file loaded via index.html:
$(function() {
var krpano = $('#krpanoSWFObject')[0];
var spotName = 'spot0';
curSpot = krpano.get(hotspot[spotName]);
console.log(curSpot)
});
Any help is welcome. Thanks in advance!
You are close to it. But I'm not sure your can get the element as you wrote it.
First, you should grab the KRPano plugin as an object and not as HTML DOM element:
var myKRPano = $('#krpanoSWFObject'); // First way, no need of "[0]"
var otherKRPano = document.getElementById("krpanoSWFObject"); // Another way
Now you got your JS object, just call "get" method. BUT you should know that "get()" executes internal code: thus you have to place your request as a string! For instance, and with your own code:
var spotname = "spot0";
var query = "hotspot['"+spotname+"']"; // i.e. "hotspot['spot0']"
var myHotspot = myKRPano.get(query); // or myKRPano.get("hotspot['spot0']");
This will provide you with something like:
Object { _type="hotspot", DATA={...}, plugin={...}, plus...}
From there, you can ask for
> myHotspot.atv
-10.5868612
> myHotspot.name
"spot0"
Don't hesitate to use a debug tool for your browser when working with KRPano, as a general advice. Then you can directly try your code and get the issue.
If you do so, you would see that "$('#krpanoSWKObject').get()" is set while "$('#krpanoSWKObject')[0].get()" is not. :)
Regards,
what are you supposed to do by getting the hotspot?
If you need to get some hotspot attribute via javascript you can call a js method in the xml < action > tag and get the attributes directly from the xml hotspot:
in the javascript file, gets the ath and atv attributes of a hotspot and
returns an array
function getspotcoords(ath,atv){
var spotcoords = [ath,atv];
return spotcoords
}
in the xml call the function in the < action /> tag, triggered when click on the hotspot
<hotspot name="myhotspot" onclick="myaction"/>
<action name="myaction">
//js() method is required!
js(getspotcoords(get(hotspot[0].ath), get(hotspot[0].atv)));
</action>
you can get the hotspot itself in the same way, and store it in a variable in the javascriptfile.
Hope it works!

Convert HTML tags to WordML with JavaScript

Do you know any way to convert HTML tags to WordML only using JavaScript. I need to get the content of a DOM element and convert what is inside to WordML.
Looking on npm there doesn't seem to be a library for this already.
So I think you're going to have to make your own. That being said, WordML is just a particular flavor of XML, right? This is the WordML you are referring to?
So to get the content of of a DOM element is pretty easy, you can do that with jQuery.
var ele = $('#wordml-element');
From there you will now want to convert it into WordML compatible XML. You could try using the xml library on npm for this.
So you will be transforming tree structured DOM elements into tree structured XML elements. The recommended pattern for doing this is known as the Visitor Pattern.
From there you will be left with an XML structure which you can further manipulate using the same pattern. At the end you will convert the XML structure into a string and that is what you will save to a file.
Now since I don't really know the structure of the HTML you are trying to convert into WordML I can only give you a very general code solution to the problem, which may look something like this:
var xml = require('xml')
function onTransformButtonClick() {
var options = {} // see documentation
var ele = $('#wordml-element')[0]
var wordml = transformElement(ele)
var text = xml(wordml, options);
fileSave(text);
}
function transformElement(ele) {
switch(ele.tagName) { // You could use attributes or whatever
case 'word-document':
return transformDocument(ele);
case 'word-body':
return transformBody(ele);
case 'word-p':
return transformParagraph(ele);
case 'word-r':
return transformRun(ele);
case 'word-text':
return transformText(ele);
}
}
function transformDocument(ele) {
var wordDocument = xml.element({...})
ele.childNodes.forEach(function (child) {
wordDocument.push(transformElement(child))
})
return [wordDocument]
}
function transformBody(ele) {
// create new element via xml library...
}
function transformParagraph(ele) {
// create new element via xml library...
}
function transformRun(ele) {
// create new element via xml library...
}
function transformText(ele) {
// create new element via xml library...
}
The specific implementations of which I will leave up to you since I don't know enough details to give you a more detailed answer.

CQ5 AEM: how to get a component by name within a dialog using javascript

I know this will probably a simple question, but I'm new to CQ5 and AEM in general.
I have a cq:Widget node which is a simple textfield.
<rowtitlevalue
jcr:primaryType="cq:Widget"
fieldLabel="Row Title Value"
name="./rowtitlevalue"
xtype="textfield"
disabled="true"/>
Now at the moment within my JavaScript, I'm currently accessing it via
var textfield = panel.findByType('textfield')[1];
which works fine (there's another textfield before this one, hence the 1 in the array.
MY QUESTION:
how do I look for this field using it's NAME attribute within my javascript.
Any help would be appreciated.
Also, I'm using this object to run the following:
if (show != undefined) {
textfield.enable();
textfield.show();
}
else if (show == undefined) {
textfield.disable();
textfield.hide();
}
The JavaScript is located within the Component Based ClientLibs.
And this is the Listener that I have under the checkbox that defines the value of SHOW within the javascript (which is working fine).
<listeners
jcr:primaryType="nt:unstructured"
loadcontent="function(field,rec,path){Ejst.toggleRowTitle(field);}"
selectionchanged="function(field,value){Ejst.toggleRowTitle(field);}"/>
Please let me know if you see any problems with this.
Appreciate it in advance
The CQ.Dialog API defines the getField( String name) method which returns a field with the given name. In case more than one field with the same name exists, it returns an array of those fields.
Thus finding parent of xtype dialog instead of panel as shown below would solve this.
Ejst.toggleRowTitle = function(checkbox) {
var dlg = checkbox.findParentByType('dialog');
var rowTitleField = dlg.getField('./rowtitlevalue');
// perform required operation on rowTitleField
}
i did something like that a few days ago and my solution was to make a js file on the same level of the component and with the same name of the component with the information that i need.
Something like this:
The file will be called rowtitlevalue.js and the content would be:
"use strict";
use(function() {
var data = {};
data.rowtitlevalueData = properties.get("rowtitlevalue");
//more properties if needed...
return {
data: data
}
});
then where i need to use it in javascript, i need the following tags:
<sly data-sly-use.data="rowtitlevalue.js">
<script type="text/javascript">
var myVariable = ${data.rowtitlevalueData};
</script>
</sly>

retrieving gravatar using jquery knockout js

I am trying to get the gravatar of multiple uses to be displayed in one page and i am using a foreach loop for that. Also i am using knockout js to get the information like email and name and returned as json. Since i cannot use razor with gravatar because it requests a string to be passed in as an email and what i have are returned "data-bind="text:Email"
I am trying to use the MD5 concept and i am very new to this and not sure if i am following the right steps. I found this online from google code: http://www.devcurry.com/2012/06/retrieving-gravatar-using-jquery.html
and i tried to implement but not sure if my code is properly written:
Part of my javascript related to what i am doing:
$.views.Games.UserViewModel = function (data) {
var self = this;
self.Name = ko.observable(data.Name);
self.Email = ko.observable(data.Email);
self.Hash = CryptoJS.MD5(Email);
};
My View Page:
<img alt="Gravatar" title="My Gravatar" data-bind="attr:{href:'http://www.gravatar.com/avatar/' +Hash()+'?s=30&d=identicon&r=G'}" />
With this i am not getting a gravatar to show. Any helpful information or tips is greatly appreciated.
Code update
I altered so this is how it looks:
view model
public string MD5Email { get{ return Email.MD5Hash(); } }
javascript
self.MD5Email = ko.observable('http://www.gravatar.com/avatar/' + data.MD5Email + '?s=30&d=identicon&r=G');
view page
<img width="158" height="158" alt="Gravatar" data-bind="attr:{'src':MD5Email()}"/>
First, don't put JS logic in your data-binds. Use a computed instead:
self.GravatarUrl = computed(function() {
return 'http://www.gravatar.com/avatar/' + self.Hash() + 's=30&d=identicon&r=G';
});
Second, your Hash needs to be a computed observable as well. The way you have it now, it's only evaluated once, when the JS first runs, and when most likely Email is null. So your Gravatar URL is never being populated with a valid email hash.
self.Hash = computed(function() {
return CryptoJS.MD5(self.Email);
});
However, since this Hash computed is only being used to serve the other computed at this point, you can and should probably just combine the two:
self.GravatarUrl = computed(function() {
var hash = CryptoJS.MD5(self.Email);
return 'http://www.gravatar.com/avatar/' + hash + 's=30&d=identicon&r=G';
});
Then, your data-bind becomes simply:
<img alt="Gravatar" title="My Gravatar" data-bind="attr:{ href: GravatarUrl }" />
Much cleaner.
UPDATE based on OP's update
I'm not sure why you changed the logic of the code I gave you, but that's why it's not working.
First, it seems you've given up on MD5 in Javascript and added it to your view model. That's fine, but you've introduced the same logic problem you had earlier by setting the self.MD5Email to the entire URL based on data.Email. This is not a computed and data.Email is not an observable. It exists only at the initial creation of the KO view model. What you should be doing is something like:
self.MD5Email = ko.observable(data.MD5Email);
self.Gravatar = ko.computed(function () {
return 'http://www.gravatar.com/avatar/' + self.MD5Email() + '?s=30&d=identicon&r=G'
});
You've rightly corrected setting the img src instead of href (I missed that too), but using the parenthesis is unnecessary when you're not doing other JS logic at the same time, so it should just be:
data-bind="attr: { src: Gravatar }"
Not sure if this helps but I wrote a binding to do just this recently:
https://github.com/grofit/knockout.gravatar
So you can just use it using the knockout binding goodness.

Categories