javascript var into onClick in html - javascript

I have a var I need to be sent as a JSON string for AS3. It has to be sent as printed out in the link. How can I get my var to be in the onClick of an html as seen below?
<script>
var NeedMyVarHere = {
One:"This is var one!",
Two:"This is JSON Object 2"
};
NeedMyVarHere = JSON.stringify(NeedMyVarHere);
</script>
<a href="javascript:void(0);" onclick="AirBridge.evoke('myCustomFunction(NeedMyVarHere)')" return false;>Testing!</a>
UPDATE to clarify.
The AS requires a "string be sent" but you can declare a custom function in a string. I didn't write the class. I just need a JSON object written in String format inside my onClick. Like this:
onClick="AirBridge.evoke('myCustomFunction({One:"This is var one!",Two:"This is var Two"})"
But I am hoping to use a single var to print it out like...
onClick="AirBridge.evoke('myCustomFunction(NeedMyVarHere)"
I hope that makes sense.

This is explained in details here https://github.com/myflashlab/webView-ANE/issues/48 but yet, here's a copy:
in your JS, create a button or link to call a JS function
<button type="button" onClick="sendComplexDataToAir()">Send Complex Data To Air</button>
in your js code, create your Json and send it back to Air like this:
function sendComplexDataToAir()
{
var myJSONObject =
{
"someData":
[
{"var1": "value 1"},
{"var2": "value 2"},
{"var3": "value 3"},
{"var3": "As long as you have a valid Json in JS, you can have it received on the Air side with no problem!"}
]
};
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
var jsonStr = JSON.stringify(myJSONObject);
// http://www.w3schools.com/jsref/jsref_encodeURI.asp
var encodedStr = encodeURIComponent(jsonStr);
// and finally send it to flash
AirBridge.evoke('parseJson('+ encodedStr +')');
}
then, receive it on the Air side like this
private function onReceivedMassage(e:RichWebViewEvent):void
{
DynamicFunc.run(this, e.param);
}
public function parseJson($str:String):void
{
trace(decodeURIComponent($str));
}

Better to use unobtrusive JavaScript using addEventListener. But for this solution, I would say:
onclick="AirBridge.evoke('myCustomFunction(NeedMyVarHere)')" return false;
//---------------------------------------------------------^ " prematurely closed.
Change to:
onclick="AirBridge.evoke('myCustomFunction(' + NeedMyVarHere.One + ')'); return false;"
Or:
onclick="AirBridge.evoke('myCustomFunction(NeedMyVarHere)'); return false;"

Can you not do something like illustrated below?
<script>
var NeedMyVarHere = {
One:"This is var one!",
Two:"This is JSON Object 2"
};
NeedMyVarHere = JSON.stringify(NeedMyVarHere);
function onClickFunction() {
Airbridge.evoke(myCustomFunction(NeedMyVarHere));
}
</script>
Testing!
This way the onClick-function doesn't need to accept an argument but can call the parameterless function 'onClickFunction' which then calls the function (with the argument) you wanted to call in the first place.

The problem with your code is it is not passing the reference to the variable since it is just a hardcoded string. Since it needs to be a string, you are better off using addEventListener and build the string instead of an inline event.
xxxx
and the script
document.getElementById("myLink").addEventListener("click", function (e) {
AirBridge.evoke("myCustomFunction('" + JSON.stringify(NeedMyVarHere) + "')");
return false; // or e.preventDefault();
});
Make sure this line runs after the element is added to the page (document ready, onload, or just in the body after the element.)

Related

Modify javascript that was downloaded as part of a web page

I would like to modify the Javascript that is downloaded as part of a web page.
I have this page:
https://discussions.apple.com/thread/7629335
I would like to modify the function jspaginate.init. I've gotten this far:
console.log(window.jspaginate)
Object { data: Object, loading: false, init: jspaginate.init(), update: jspaginate.update(), pushState: jspaginate.pushState(), loadingSequence: jspaginate.loadingSequence(), removeLoading: jspaginate.removeLoading(), updateUI: jspaginate.updateUI(), getData: jspaginate.getData() }
undefined
console.log(window.jspaginate["init"])
function jspaginate.init()
console.log(window.jspaginate["init"].toString())
function (action, last){
var view = this,
target, current;
... clipped ...
background:
This page includes lots of javascript. The function jspaginate is download from the site server. Nevertheless, I need to change the function jspaginate. I do not have access to the server. I want to change my copy of jspaginate. I know that I need to change the function every time it is downloaded.
I'm using GreaseMonkey to insert some javascript.
Just override the init function with its new definition, like below:
window.jspaginate.init = function() {
console.log('there you go');
}
Here is the code I used. Since I had converted jspaginate.init to a string and modified the string, I had to convert the string to a function. I did the conversion via the eval function.
var debug = 1;
/* Get the string of the function to change */
var stringed = jspaginate["init"].toString();
if ( debug ) console.log ("--> cloneGotoChange: \n" + stringed);
/* Place the added code as the last statement in the function jspaginate["init"]
Find the function closing } */
position = stringed.lastIndexOf("}");
/* Change the downloaded javascript */
var newCode = stringed.substr(0, position)
+ " console.log (\"--> before \" ); cloneGotoUpate(); console.log (\"--> after \" ); "
+ stringed.substr(position);
/* Inject the changed code
need to use the eval function to make a function assignment instead of a string assignment */
eval( 'jspaginate["init"] =' + newCode);
if ( debug ) console.log (console.log(window.jspaginate["init"].toString()));

using $.extend() to add more cases to a switch statement function in jQuery?

Fiddle Example
I have a function called parseData to render html presentation from returned json data in the main js file.
var data = {
"title": "This is news"
};
$("button").click(function(){
var feedformat = $(this).data('format');
item_html = parseData(feedformat, data);
$('.feedback').append(item_html);
});
function parseData(type, data) {
var item_html = '';
switch(type) {
case 'story':
item_html = '<h5>'+data.title+'</h5>';
break;
}
return item_html;
}
My question is, is it possible to use $.extend to add more cases from another script file that is dynamically pulled in on click using getscript? Suppose I have a new case called oldnews. That case contains a lot of html tags but won't be used often, so I don't want to store it in the main js file and would like to bring it in only when people want it. Call I use something like the following in another script file to extend parseData which is in the main js file?
(function($){
var addcase = $.fn.parseData;
$.fn.addcase = function( type,data ) {
case 'oldnews':
item_html = '<div>'+data.title+',but outdated</div>';
break;
};
}(jQuery));
This sounds pretty easy, actually. What you're really trying to do is map the names of data formats to functions that produce HTML output. You could easily encode what you've already demonstrated here with this:
var parseFunctions = {
story: function(data) {
return '<h5>' + data.title + '</h5>';
},
oldnews: function(data) {
return '<div>' + data.title + ', but outdated</div>';
}
}
When it is time to output some html you can do this:
$("button").click(function(){
var format = $(this).data('format');
if (typeof parseFunctions[format] == 'function')
$('.feedback').append( parseFunctions[format](data) );
});
This works because Javascript treats functions like any other value. You can assign them to variables, copy them, etc.. With this technique you can extend the base parseFunctions object with a another object containing functions. The main thing you have to look out for is key collision. (Two people trying to define a function for data type 'some_type'.)
Instead of switch/case statements, you could do something more extensible like looping over a container of news item qualifiers and their associated data. In JSON this might look like:
{
"story": {
"html": "<h5>%s<\/h5>"
},
"oldnews": {
"html": "<div>%s, but outdated<\/div>"
}
}
If you have a JavaScript object like that, you make it visible to parseData, which gets the "html" value of whichever one matches "type" and replaces "%s" with the title. Whenever new "cases" are pulled in, you use _.extend or $.extend to add to the structure.

Cant get the current id of a data from local Storage using jquery

I am working on an app to store data offline. My problem is when I try to retrieve the data from local storage for update/edit, it keeps calling only the id of the first item, and not calling the id of the data in view.
Please what am I doing wrong?
Here is my code for loading employees:
// load cases from localStorage
var employees;
if (localStorage.getItem('employees')) {
employees = JSON.parse(localStorage.getItem('employees'));
} else {
// If no cases, create and save them
employees = [];
// offling storing of our cases
localStorage.setItem('employees', JSON.stringify(employees));
}
// show case listing in list view page
var showEmployees = function () {
//erase existing content
$('#employee_list').html('');
//insert each employee
for (var i = 0; i<employees.length; i++) {
addEmployees(employees[i]);
}
};
Here is my code to add an employee to list view:
//add an eliment to list view
var addEmployees = function (empData) {
//HTML content of one list element
var listElementHTML = '<li><a class="employee_list" ui-btn ui-btn-e ui-btn-icon-right ui-icon-carat-r" data-transition="fade" data-split-icon="delete" href="#item'+empData.id+'">' + empData.employeename + '<br> ' + empData.dateofbirth + '</br></a></li>';
//appending the HTML code to list view
$('#employee_list').append(listElementHTML);
};
Here is my code for Edit function:
//User input to edit form
$('#edit_employee_page').on('click' , function () {
var editEmployee = JSON.stringify({
id: employees.length+1,
employeeno: $('#employeeno').val(),
employeename:$('#employeename').val(),
stateoforigine:$('#stateoforigine').val(),
employeephone: $('#employeephone').val(),
dateofbirth:$('#dateofbirth').val()
});
//Alter the slected data
localStorage.setItem("employees", JSON.stringify(employees));
return true;
});
for (var i in employees) {
var id = JSON.parse(localStorage.getItem(employees[i]));
}
Here is my code for the Edit button:
//register Edit button
$('.edit_button').live('click', function (e) {
alert('I was Cliked!');
e.stopPropagation();
$.each(employees, function(a, b) {
//if(b.id == employees[i]){
$('#id').val(b.id);
$('#employeeno').val(b.employeeno);
$('#employeename').val(b.employeename);
$("#stateoforigine").val(i.stateoforigine);
$('#employeephone').val(b.employeephone);
$('#dateofbirth').val(b.dateofbirth);
$("#id").attr("readonly","readonly");
$('#employeeno').focus();
$.mobile.changePage('#edit_employee_page');
return false;
//}
});
});
Here is my local Storage:
[
{"id":1,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1965"},
{"id":2,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1966"},
{"id":3,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1966"},
{"id":4,
"employeeno":"DAST/003/2003",
"employeename":"Gold Base",
"stateoforigine":"",
"employeephone":"",
"dateofbirth":"12/03/1986"}
]
Thanks for helping me out
The way you are storing your employees into localStorage is correct, but the way you are getting them out is incorrect. You stored your employees by stating:
localStorage.setItem("employees", JSON.stringify(employees));
So, in order to retrieve them, you must use:
var employees = JSON.parse(localStorage.getItem("employees"));
You see, you stored the data as a string with a key of "employees"; therefore, you can only retrieve it by that key. Since all data stored in localStorage is saved as a string, you must use JSON.parse() to convert the data back into an object - an array in this case. Then you can iterate over your employees.
Update:
You should be running this code as soon as the page is rendered (see below). I'm not sure how you're doing that - if you're using an IIFE or jQuery's document.ready() function. I don't think it's necessary to store an empty array into localStorage if none were loaded initially, so, I took your else clause out.
var employees = [];
if (localStorage.getItem('employees') !== null) {
employees = JSON.parse(localStorage.getItem('employees'));
}
Debug this line-by-line when it runs and make positive your employees variable contains data. If it doesn't contain data, well then, there's nothing to edit.
If, however, there is data, then execute your showEmployees() function. Oddly, I'm not seeing in your code where you actually call this. Is it bound to a button or action in your UI? Also, what is that for loop doing after your $('#edit_employee_page') click event function? It's trying to read data from localStorage improperly and it does nothing.
I think if you simply stepped through your code one line at a time using breakpoints and desk-checking your inputs/outputs you'd find out where you're going wrong.
It also appears that there's a disconnect in your code. May be you left out some lines; you define a string editEmployee but out of the blues you store JSON.stringify(employees) whereas employees is not defined in your code:
$('#edit_employee_page').on('click' , function(){
var editEmployee = JSON.stringify({
id: employees.length+1,
//........
});
//Alter the slected data
localStorage.setItem("employees", JSON.stringify(employees));
return true;
});
I had a similar task to do . I did it this way.
I passed the dynamic Id to be passed as an id attribute
id="'+empData.id+'"
and then inside the
$('.edit_button').live('click', function (e) {
alert('I was Cliked!');
var empId=$(this).attr('id');
rest of the code is same.

Is it bad to add JSON on HTML data attribute?

Since HTML data attribute allows adding any custom data, I wonder if it is a good idea to include a set of JSON list as a data attribute? Then, the corresponding JSON can be easily accessed by JavaScript events with getAttribute("data-x").
In fact, my question is that: Is it standard, efficient, and reasonable to add a large set of data to an HTML attribute?
For example
<div data-x="A LARGE SET OF JSON DATA" id="x">
Or a large set of JSON data must be stored within <script> tag, and an HTML attribute is not a right place for a large set of data, even for data attribute.
Instead of storing everything in the data attribute you could use an identifier to access the data.
So for example you could do this :
var myBigJsonObj = {
data1 : { //lots of data},
data2 : { //lots of data}
};
and then you had some html like so :
<div data-dataId="data1" id="x">
You can use jquery to get the data now like so :
var dataId = $('#x').attr('data-dataId');
var myData = myBigJsonObj[dataId];
This is the best approach imho.
Say you want to save the object var dataObj = { foo: 'something', bar: 'something else' }; to an html data attribute.
Consider first stringifying the object such that we have
var stringifiedDataObj = JSON.stringify(dataObj);
Then you can use jQuery to set the stringifiedDataObj as the data attribute e.g. with the jQuery.data() API
While there's nothing to stop you embedding a long string of JSON in a data attribute, arguably the more "correct" way of doing it would be to add one data attribute per property of the JSON data. eg:
Javascript:
var dataObj = { foo: 'something', bar: 'something else' }
HTML:
<div data-foo="something" data-bar="something else"></div>
This way each piece of data in the JSON object corresponds to a separate, independently-accessible piece of data attached to the DOM element.
Bear in mind that either way you'll need to escape the values you're inserting into the HTML - otherwise stray " characters will break your page.
Technically you can, and I have seen several sites do this, but another solution is to store your JSON in a <script> tag and put a reference to the script tag in the data attribute. This is a better solution than just storing the data as a JS object in an actual script if the data is rendered to the page server-side, but there are CSP restrictions on inline script tags, for example.
HTML
<div data-data-id="#MyScriptData" id="x"></div>
<script type="application/json" id="MyScriptData">
{
"fruit": "apple",
...
}
</script>
JS
$(function () {
var dataId = $("#x").data("data-id");
var dataTag = $(dataId);
var dataJson = dataTag.html(); // returns a string containing the JSON data
var data = JSON.parse(dataJson);
...
});
You could make use of Map. Where your element will be the key, and the value at that key could be an object in which you store wanted data. Something like this (not tested though):
(function(global) {
const map = new Map();
global.CustomData = {
add(element, key, data) {
if (!map.has(element)) {
map.set(element, {});
}
map.get(element)[key] = data;
return map.get(element);
},
get(element, key) {
if (!map.has(element)) {
return null;
}
if (key !== undefined) {
return map.get(element)[key];
}
return map.get(element)
},
remove(element, key) {
if (!map.has(element)) {
return false;
}
delete map.get(element)[key];
if (Object.keys(map.get(element)).length === 0) {
map.delete(element);
}
return true;
},
clear(element) {
if (!map.has(element)) {
return false;
}
map.delete(element);
return true;
}
}
})(window);

Why does the DOM remain unchanged, even though the console outputs what the correct result should be when trying to change link attributes?

function makeLinks(context, url) {
var sets = context ? $(context + ' a') : $('a'),
prot = url || window.location.protocol;
if(prot.match(/https/)){
lockup(sets);
}
function lockup(elem) {
elem.each(function(){
var self = $(this),
href = self.attr('href');
if(href.match(/http[^s]/)){
// This logs the correct output
console.log(href.replace('http','https'));
// This fails
href.replace('http','https');
}
});
}
}
The purpose of the function is to check the current protocol of the window object.
If it is 'https:', then I want the anchors that have a href of 'http' to be 'https'.
The function is called like this: makeLinks('#wrapper', 'https:');
The second parameter is just for testing, otherwise it would use window.location.protocol
Currently, when I call this function on markup that looks like this:
<div id="wrapper">
</div>
The console logs exactly what I want to happen, however, the actual href remains unchanged inside of the DOM.
I've tested this out in Chrome and Firefox with the same result
I'm pretty sure that my logic is wrong somewhere (or everywhere)
If someone can help me understand why, I would be very appreciative :)
You're not doing anything with the result of the .replace().
You need to set the new value.
self.attr('href', href.replace('http','https'));
or a nicer way is like this:
function lockup(elem) {
elem.attr('href', function(i, href) {
return href.match(/http[^s]/) ? href.replace('http','https') : href;
});
}
Should this not be something Like Below
if(href.match(/http[^s]/)){
// This logs the correct output
console.log(href.replace('http','https'));
// This fails
href.replace('http','https');
}
});
Change to:
if(href.indexOf('https') == -1) {
console.log(href.replace('http','https'));
href.replace('http', 'https');
}

Categories

Resources