Why are these variables getting cleared/reset? - javascript

I am attempting to write a small library for scrolling events in JavaScript, but I must be missing something easy, because it seems that my vars are getting reset at some point inside of this method.
Here is the code:
var scrollEvents = {
change: window.onscroll = function (selector, property, initialValue, changedValue) {
// grab the selectors and convert them into an array so we can use forEach()
var items = document.getElementsByClassName(selector);
var itemArray = [].slice.call(items);
// window.pageYOffset has better compatibility than document.body.scrollTop
var scrollPos = window.pageYOffset;
var breakPoint = 10;
if (scrollPos > breakPoint) {
console.log('if');
console.log(items);
console.log(itemArray);
itemArray.forEach(function (i) {
i.setAttribute("style", property + ": " + changedValue + ";");
console.log("style", property + ": " + changedValue + ";")
});
} else {
console.log('else');
console.log(itemArray);
itemArray.forEach(function (i) {
i.setAttribute("style", property + ": " + initialValue + ";");
});
}
}
};
And I would like to call it like so:
scrollEvents.change("foo", "height", "400px", "800px");
I have quite a few extra console.log() calls inside there because I have been trying to diagnose the issue, but I have rewritten the code several times and seem to have hit a dead end.
The behavior I would like is that I can call scrollEvents.change() passing those parameters to change style attributes at certain scroll points.
Here is the code without all the extra console.log()'s:
var scrollEvents = {
change: window.onscroll = function (selector, property, initialValue, changedValue) {
// grab the selectors and convert them into an array so we can use forEach()
var items = document.getElementsByClassName(selector);
var itemArray = [].slice.call(items);
// window.pageYOffset has better compatibility than document.body.scrollTop
var scrollPos = window.pageYOffset;
var breakPoint = 10;
if (scrollPos > breakPoint) {
itemArray.forEach(function (i) {
i.setAttribute("style", property + ": " + changedValue + ";");
});
} else {
itemArray.forEach(function (i) {
i.setAttribute("style", property + ": " + initialValue + ";");
});
}
}
};
UPDATE:
Thanks to #pointy this library now works: https://github.com/ryanpcmcquen/scrollEvents

You've set up an object with a property called "change", and you've assigned a function to that property. The assignment also assigned the function to the "onscroll" property of the window object.
When the browser detects a user scroll operation, it will invoke that function, and regardless of your formal parameter list in the declaration it'll pass either nothing (Internet Explorer) or an event object.
Making a call to scrollEvents.change will invoke the event handler function, but that will have no effect on how the browser invokes the event handler when the user messes with the scrollbar or mouse wheel (or whatever).
I'm not sure exactly how you intend for this API to work, so it's hard to say how to fix it. If you want to attach just one event handler at a time, then the simplest thing to do would be to wrap your current code in another function:
var scrollEvents = {
change: function (selector, property, initialValue, changedValue) {
window.onscroll = function(event) {
// grab the selectors and convert them into an array so we can use forEach()
var items = document.getElementsByClassName(selector);
var itemArray = [].slice.call(items);
// window.pageYOffset has better compatibility than document.body.scrollTop
var scrollPos = window.pageYOffset;
var breakPoint = 10;
if (scrollPos > breakPoint) {
itemArray.forEach(function (i) {
i.setAttribute("style", property + ": " + changedValue + ";");
});
} else {
itemArray.forEach(function (i) {
i.setAttribute("style", property + ": " + initialValue + ";");
});
}
};
}
};
Now when you call
scrollEvents.change("foo", "height", "400px", "800px");
then that function call will establish the event handler.

Related

How to create a custom loop?

I made a custom loop that delays 300ms on it's each iteration. But in this loop, the line ul.syle.height = i + 'px'; is throwing a error that TypeError: Cannot set property 'height' of undefined at main.js
But the variable ul is working fine above at the line var ul_scrollHeight = ul.scrollHeight;.
Then why it is not working inside 'setTimeout'? Here getNextSibling is another function in my code.
function fun1() {
var ul = getNextSibling(this);
var ul_scrollHeight = ul.scrollHeight;
var i = 1;
function customLoop() {
setTimeout(function () {
ul.syle.height = i + 'px'; // Not Working
if (i <= ul_scrollHeight) {
customLoop();
}
}, 300)
}
customLoop();
}
I think you just have a typo on that line:
ul.syle.height = i + 'px';
Because ul.syle is missing a t, so that returns undefined, which did not have a property height. 🙂

using requestAnimationFrame

I'm using this function to set a transform property of some elements,but the animation is not so smooth in firefox and it's less smooth when window size is bigger(in any browser).I have read a lot of thing's on blogs which are saying that I can make much smoother animation using requestAnimationFrame,but I don't understand how I can implement it inside of my function.Can somebody explain me how I can use it inside of my function?
function sectionMovement(delay,section) {
setTimeout(function () {
var val = ((v.sectionIndex + 1) > v.leavingSection) ?
val = 100 :
val = 0;
document.getElementById("sec_"+section+"").style.transform = "translateY(-"+val+"%)"
}, delay);
};
Something like this:
function updateSection(selector) {
var elem = document.getElementById("sec_" + section);
return function step() {
var val = ((v.sectionIndex + 1) > v.leavingSection) ? // not sure what 'v' is?
100 :
0;
elem.style.transform = "translateY(-"+val+"%)";
requestAnimationFrame(step);
}
}
var sel = "myElementId";
requestAnimationFrame(updateSection(sel));
You will also likely want an external variable to check against to know when to stop the animation.

How can I make window.showmodaldialog work in chrome 37?

We have a huge web application where we use window.showmodaldialog for alerts, confirmations and popups. Since Chrome version 37 this call has been disabled.
Is there any quick workaround to make window.showmodaldialog work in the latest version of Chrome?
I am adding here a workaround for window.showmodaldialog, although this is not a perfect workaround because this will not break the code execution as showmodaldialog was doing, instead this will open the popups.
window.showModalDialog = function (url, arg, feature) {
var opFeature = feature.split(";");
var featuresArray = new Array()
if (document.all) {
for (var i = 0; i < opFeature.length - 1; i++) {
var f = opFeature[i].split("=");
featuresArray[f[0]] = f[1];
}
}
else {
for (var i = 0; i < opFeature.length - 1; i++) {
var f = opFeature[i].split(":");
featuresArray[f[0].toString().trim().toLowerCase()] = f[1].toString().trim();
}
}
var h = "200px", w = "400px", l = "100px", t = "100px", r = "yes", c = "yes", s = "no";
if (featuresArray["dialogheight"]) h = featuresArray["dialogheight"];
if (featuresArray["dialogwidth"]) w = featuresArray["dialogwidth"];
if (featuresArray["dialogleft"]) l = featuresArray["dialogleft"];
if (featuresArray["dialogtop"]) t = featuresArray["dialogtop"];
if (featuresArray["resizable"]) r = featuresArray["resizable"];
if (featuresArray["center"]) c = featuresArray["center"];
if (featuresArray["status"]) s = featuresArray["status"];
var modelFeature = "height = " + h + ",width = " + w + ",left=" + l + ",top=" + t + ",model=yes,alwaysRaised=yes" + ",resizable= " + r + ",celter=" + c + ",status=" + s;
var model = window.open(url, "", modelFeature, null);
model.dialogArguments = arg;
}
Just put this code in the head section of page.
I put the following javascript in the page header and it seems to work. It detects when the browser does not support showModalDialog and attaches a custom method that uses window.open, parses the dialog specs (height, width, scroll, etc.), centers on opener and sets focus back to the window (if focus is lost). Also, it uses the URL as the window name so that a new window is not opened each time. If you are passing window args to the modal you will need to write some additional code to fix that. The popup is not modal but at least you don't have to change a lot of code. Might need some work for your circumstances.
<script type="text/javascript">
// fix for deprecated method in Chrome 37
if (!window.showModalDialog) {
window.showModalDialog = function (arg1, arg2, arg3) {
var w;
var h;
var resizable = "no";
var scroll = "no";
var status = "no";
// get the modal specs
var mdattrs = arg3.split(";");
for (i = 0; i < mdattrs.length; i++) {
var mdattr = mdattrs[i].split(":");
var n = mdattr[0];
var v = mdattr[1];
if (n) { n = n.trim().toLowerCase(); }
if (v) { v = v.trim().toLowerCase(); }
if (n == "dialogheight") {
h = v.replace("px", "");
} else if (n == "dialogwidth") {
w = v.replace("px", "");
} else if (n == "resizable") {
resizable = v;
} else if (n == "scroll") {
scroll = v;
} else if (n == "status") {
status = v;
}
}
var left = window.screenX + (window.outerWidth / 2) - (w / 2);
var top = window.screenY + (window.outerHeight / 2) - (h / 2);
var targetWin = window.open(arg1, arg1, 'toolbar=no, location=no, directories=no, status=' + status + ', menubar=no, scrollbars=' + scroll + ', resizable=' + resizable + ', copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
targetWin.focus();
};
}
</script>
From http://codecorner.galanter.net/2014/09/02/reenable-showmodaldialog-in-chrome/
It's deprecated by design. You can re-enable showModalDialog support, but only temporarily – until May of 2015. Use this time to create alternative solutions.
Here’s how to do it in Chrome for Windows. Open Registry Editor (regedit) and create following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\EnableDeprecatedWebPlatformFeatures
Under the EnableDeprecatedWebPlatformFeatures key create a string value with name 1 and value of ShowModalDialog_EffectiveUntil20150430. To verify that the policy is enabled, visit chrome://policy URL.
UPDATE: If the above didn’t work for you here’s another method to try.
Download Chrome ADM templates from http://www.chromium.org/administrators/policy-templates
Extract and import policy relevant to your locale (e.g. windows\adm\en-US\chrome.adm. You can import either via gpedit.mscor using these utilities on Home editions of windows: http://blogs.technet.com/b/fdcc/archive/2008/05/07/lgpo-utilities.aspx)
Under “Adminstrative Templates” locate Google Chrome template and enable “Enable Deprecated Web Platform Feautes”.
Open the feature and add “ShowModalDialog_EffectiveUntil20150430″ key.
A very good, and working, javascript solution is provided here :
https://github.com/niutech/showModalDialog
I personnally used it, works like before for other browser and it creates a new dialog for chrome browser.
Here is an example on how to use it :
function handleReturnValue(returnValue) {
if (returnValue !== undefined) {
// do what you want
}
}
var myCallback = function (returnValue) { // callback for chrome usage
handleReturnValue(returnValue);
};
var returnValue = window.showModalDialog('someUrl', 'someDialogTitle', 'someDialogParams', myCallback);
handleReturnValue(returnValue); // for other browsers except Chrome
This article (Why is window.showModalDialog deprecated? What to use instead?) seems to suggest that showModalDialog has been deprecated.
The window.returnValue property does not work directly when you are opening a window using window.open() while it does work when you are using window.showModalDialog()
So in your case you have two options to achieve what you are trying to do.
Option 1 - Using window.showModalDialog()
In your parent page
var answer = window.showModalDialog(<your page and other arguments>)
if (answer == 1)
{ do some thing with answer }
and inside your child page you can make use of the window.returnValue directly like
window.returnValue = 'value that you want to return';
showModalDialog halts the executions of the JavaScript until the dialog box is closed and can get a return value from the opened dialog box when its closing.But the problem with showModalDialog is that it is not supported on many modern browsers. In contrast window.open just opens a window asynchronously (User can access both the parent window and the opened window). And the JavaScript execution will continue immediately. Which bring us to Option 2
Option 2 - Using window.open()
In your parent page write a function that deals with opening of your dialog.
function openDialog(url, width, height, callback){
if(window.showModalDialog){
options = 'dialogHeight: '+ height + '; dialogWidth: '+ width + '; scroll=no'
var returnValue = window.showModalDialog(url,this,options);
callback(returnValue)
}
else {
options ='toolbar=no, directories=no, location=no, status=yes, menubar=no, resizable=yes, scrollbars=no, width=' + width + ', height=' + height;
var childWindow = window.open(url,"",options);
$(childWindow).on('unload',function(){
if (childWindow.isOpened == null) {
childWindow.isOpened = 1;
}
else {
if(callback){
callback(childWindow.returnValue);
}
}
});
}
}
And whenever you want to use open a dialog. Write a callback that deals with the return value and pass it as a parameter to openDialog function
function callback(returnValue){
if(returnValue){
do something nice with the returnValue
}}
And when calling the function
openDialog(<your page>, 'width px', 'height px', callbak);
Check out an article on how to replace window.showModalDialog with window.open
I wouldn't try to temporarily enable a deprecated feature. According to the MDN documentation for showModalDialog, there's already a polyfill available on Github.
I just used that to add windows.showModalDialog to a legacy enterprise application as a userscript, but you can obviously also add it in the head of the HTML if you have access to the source.
I use a polyfill that seem to do a good job.
https://github.com/niutech/showModalDialog
http://niutech.github.io/showModalDialog/demo.html
Create a cross browser ModalDialog
function _showModalDialog(url, width, height, closeCallback) {
var modalDiv,
dialogPrefix = window.showModalDialog ? 'dialog' : '',
unit = 'px',
maximized = width === true || height === true,
w = width || 600,
h = height || 500,
border = 5,
taskbar = 40, // windows taskbar
header = 20,
x,
y;
if (maximized) {
x = 0;
y = 0;
w = screen.width;
h = screen.height;
} else {
x = window.screenX + (screen.width / 2) - (w / 2) - (border * 2);
y = window.screenY + (screen.height / 2) - (h / 2) - taskbar - border;
}
var features = [
'toolbar=no',
'location=no',
'directories=no',
'status=no',
'menubar=no',
'scrollbars=no',
'resizable=no',
'copyhistory=no',
'center=yes',
dialogPrefix + 'width=' + w + unit,
dialogPrefix + 'height=' + h + unit,
dialogPrefix + 'top=' + y + unit,
dialogPrefix + 'left=' + x + unit
],
showModal = function (context) {
if (context) {
modalDiv = context.document.createElement('div');
modalDiv.style.cssText = 'top:0;right:0;bottom:0;left:0;position:absolute;z-index:50000;';
modalDiv.onclick = function () {
if (context.focus) {
context.focus();
}
return false;
}
window.top.document.body.appendChild(modalDiv);
}
},
removeModal = function () {
if (modalDiv) {
modalDiv.onclick = null;
modalDiv.parentNode.removeChild(modalDiv);
modalDiv = null;
}
};
// IE
if (window.showModalDialog) {
window.showModalDialog(url, null, features.join(';') + ';');
if (closeCallback) {
closeCallback();
}
// Other browsers
} else {
var win = window.open(url, '', features.join(','));
if (maximized) {
win.moveTo(0, 0);
}
// When charging the window.
var onLoadFn = function () {
showModal(this);
},
// When you close the window.
unLoadFn = function () {
window.clearInterval(interval);
if (closeCallback) {
closeCallback();
}
removeModal();
},
// When you refresh the context that caught the window.
beforeUnloadAndCloseFn = function () {
try {
unLoadFn();
}
finally {
win.close();
}
};
if (win) {
// Create a task to check if the window was closed.
var interval = window.setInterval(function () {
try {
if (win == null || win.closed) {
unLoadFn();
}
} catch (e) { }
}, 500);
if (win.addEventListener) {
win.addEventListener('load', onLoadFn, false);
} else {
win.attachEvent('load', onLoadFn);
}
window.addEventListener('beforeunload', beforeUnloadAndCloseFn, false);
}
}
}
(function() {
window.spawn = window.spawn || function(gen) {
function continuer(verb, arg) {
var result;
try {
result = generator[verb](arg);
} catch (err) {
return Promise.reject(err);
}
if (result.done) {
return result.value;
} else {
return Promise.resolve(result.value).then(onFulfilled, onRejected);
}
}
var generator = gen();
var onFulfilled = continuer.bind(continuer, 'next');
var onRejected = continuer.bind(continuer, 'throw');
return onFulfilled();
};
window.showModalDialog = window.showModalDialog || function(url, arg, opt) {
url = url || ''; //URL of a dialog
arg = arg || null; //arguments to a dialog
opt = opt || 'dialogWidth:300px;dialogHeight:200px'; //options: dialogTop;dialogLeft;dialogWidth;dialogHeight or CSS styles
var caller = showModalDialog.caller.toString();
var dialog = document.body.appendChild(document.createElement('dialog'));
dialog.setAttribute('style', opt.replace(/dialog/gi, ''));
dialog.innerHTML = 'Ă—<iframe id="dialog-body" src="' + url + '" style="border: 0; width: 100%; height: 100%;"></iframe>';
document.getElementById('dialog-body').contentWindow.dialogArguments = arg;
document.getElementById('dialog-close').addEventListener('click', function(e) {
e.preventDefault();
dialog.close();
});
dialog.showModal();
//if using yield
if(caller.indexOf('yield') >= 0) {
return new Promise(function(resolve, reject) {
dialog.addEventListener('close', function() {
var returnValue = document.getElementById('dialog-body').contentWindow.returnValue;
document.body.removeChild(dialog);
resolve(returnValue);
});
});
}
//if using eval
var isNext = false;
var nextStmts = caller.split('\n').filter(function(stmt) {
if(isNext || stmt.indexOf('showModalDialog(') >= 0)
return isNext = true;
return false;
});
dialog.addEventListener('close', function() {
var returnValue = document.getElementById('dialog-body').contentWindow.returnValue;
document.body.removeChild(dialog);
nextStmts[0] = nextStmts[0].replace(/(window\.)?showModalDialog\(.*\)/g, JSON.stringify(returnValue));
eval('{\n' + nextStmts.join('\n'));
});
throw 'Execution stopped until showModalDialog is closed';
};
})()
;
**Explanation:
------------**
The best way to deal with showModalDialog for older application conversions is use to `https://github.com/niutech/showModalDialog` inorder to work with show modal dialogs and if modal dailog has ajax calls you need to create object and set the parameters of function to object and pass below...before that check for browser and set the useragent...example: agentStr = navigator.userAgent; and then check for chrome
var objAcceptReject={}; // create empty object and set the parameters to object and send to the other functions as dialog when opened in chrome breaks the functionality
function rejectClick(index, transferId) {
objAcceptReject.index=index;
objAcceptReject.transferId=transferId;
agentStr = navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0) // If Internet Explorer, return version number
{
var ret = window.showModalDialog("/abc.jsp?accept=false",window,"dialogHeight:175px;dialogWidth:475px;scroll:no;status:no;help:no");
if (ret=="true") {
doSomeClick(index);
}
} else if ((agentStr.indexOf("Chrome")) >- 1){
spawn(function() {
var ret = window.showModalDialog("/abcd.jsp?accept=false",window,"dialogHeight:175px;dialogWidth:475px;scroll:no;status:no;help:no");
if (ret=="true") {// create an object and store values in objects and send as parameters
doSomeClick(objAcceptReject.index);
}
});
}
else {
var ret = window.showModalDialog("/xtz.jsp?accept=false",window,"dialogHeight:175px;dialogWidth:475px;scroll:no;status:no;help:no");
if (ret=="true") {
doSomeClick(index);
}
}
The window.showModalDialog is deprecated (Intent to Remove:
window.showModalDialog(), Removing showModalDialog from the Web
platform). [...]The latest plan is to land the showModalDialog removal
in Chromium 37. This means the feature will be gone in Opera 24 and
Chrome 37, both of which should be released in September.[...]
Yes, It's deprecated. Spent yesterday rewriting code to use Window.open and PostMessage instead.

Ordering results in JSON variable by integer

I am building a jQuery search suggestion script based upon two Google API's. Each API outputs a "relevance" integer (which I am returning next to each item to demonstrate) and I want to be able to order the results by that integer for each item.
How can I do this? I tried making the script output everything into one variable but I couldn't quite work it out.
A working demo can be seen here: http://jsfiddle.net/rEPf3/
My jQuery code is:
$(document).ready(function(){
$("#search").keyup(function(){
$.getJSON("http://suggestqueries.google.com/complete/search?q="+$("#search").val()+"&client=chrome&callback=?",function(data){
var suggestion="";
for(var key in data[1]){
if(data[4]["google:suggesttype"][key]=="NAVIGATION"){
suggestion+="<li><a href='"+data[1][key]+"'>"+data[2][key]+"</a> <i>("+data[4]["google:suggestrelevance"][key]+")</i></li>";
}else{
suggestion+="<li>"+data[1][key]+" <i>("+data[4]["google:suggestrelevance"][key]+")</i></li>";
}
}
$("#suggest").html(suggestion);
});
$.getJSON("https://www.googleapis.com/freebase/v1/search?query="+$("#search").val()+"&limit=3&encode=html&callback=?",function(data){
var suggestion2="";
for(var key in data.result){
suggestion2+="<li>"+data.result[key].name+" <i>("+data.result[key].score*4+")</i></li>";
}
$("#suggest2").html(suggestion2);
});
});
});
I think the cleanest way is to push the results from each dataset into an externally scoped variable, then sort and render from that. Example is below.
var combined = [],
completed = 0;
$(document).ready(function () {
$("#search").keyup(function () {
combined = [];
completed = 0;
$.getJSON("http://suggestqueries.google.com/complete/search?q=" + $("#search").val() + "&client=chrome&callback=?", function (data) {
for (var key in data[1]) {
if (data[4]["google:suggesttype"][key] == "NAVIGATION") {
combined.push({
href : data[1][key],
text : data[2][key],
score : parseInt(data[4]["google:suggestrelevance"][key],10)
});
} else {
combined.push({
text : data[1][key],
score : parseInt(data[4]["google:suggestrelevance"][key],10)
});
}
}
if ( ++completed == 2 ) complete();
});
$.getJSON("https://www.googleapis.com/freebase/v1/search?query=" + $("#search").val() + "&limit=3&encode=html&callback=?", function (data) {
for (var key in data.result) {
combined.push({
text : data.result[key].name,
score : parseInt(data.result[key].score,10) * 14
});
}
if ( ++completed == 2 ) complete();
});
});
});
function complete(){
console.log(combined);
combined.sort(function(a,b){ return b.score - a.score; });
var buffer = [];
combined.forEach(function(result){
buffer.push("<li>"+result.text+" <i>("+result.score+")</i></li>")
})
$("#suggest").html(buffer.join(""));
}
Edit
This solution doesn't take into account the fact that the user may be typing at a faster pace than the APIs, that API calls may not come back in order, and doesn't do anything to try to limit the number of calls made to each API. To make this behave more consistently (and more efficiently):
Change the keypress handler such that each key press cancels any previous timeouts then sets a new timeout at a reasonable delay (300ms seems a reasonable place to start) which then triggers the API calls
Wrap each API call in an immediately executed function so that you can reference the value of a global counter at the time each API call was made. Increment the counter with each keypress, and don't process the response from API calls where the counter didn't match
Here is the full code for you, you have to append all the results to one container and sort in .ajaxComplete event
$(document).ready(function () {
$("#search").keyup(function () {
$("#suggest").empty();
$.getJSON("http://suggestqueries.google.com/complete/search?q=" + $("#search").val() + "&client=chrome&callback=?", function (data) {
var suggestion = "";
for (var key in data[1]) {
if (data[4]["google:suggesttype"][key] == "NAVIGATION") {
suggestion += "<li><a href='" + data[1][key] + "'>" + data[2][key] + "</a> <i>(" + data[4]["google:suggestrelevance"][key] + ")</i></li>";
} else {
suggestion += "<li>" + data[1][key] + " <i>(" + data[4]["google:suggestrelevance"][key] + ")</i></li>";
}
}
$("#suggest").append(suggestion);
});
$.getJSON("https://www.googleapis.com/freebase/v1/search?query=" + $("#search").val() + "&limit=3&encode=html&callback=?", function (data) {
var suggestion2 = "";
for (var key in data.result) {
suggestion2 += "<li>" + data.result[key].name + " <i>(" + data.result[key].score * 4 + ")</i></li>";
}
$("#suggest").append(suggestion2);
});
$(document).ajaxComplete(function (event, xhr, settings) {
$("#suggest").html($("#suggest li").sort(function (a, b) {
return (parseInt($(a).find("i").html(), 10) > parseInt($(b).find("i").html(), 10));
}));
});
});
});
http://jsfiddle.net/rEPf3/8/
Try like this
Add this line before to the for loop
data[4]["google:suggestrelevance"].sort();
See Demo
Updated
Try combining the data sets by using a single variable
See Demo
Put them together and sort.
Following is the code.
Using promise to know both ajax requests are completed.
$(document).ready(function(){
$("#search").keyup(function(){
var mergedData = [];
var promise1 = $.getJSON("http://suggestqueries.google.com/complete/search?q="+$("#search").val()+"&client=chrome&callback=?",function(data){
var suggestion="";
console.log(data);
var arr = [];
for(var i in data[1]){
arr[i] = {value : data[1][i], rel : data[4]['google:suggestrelevance'][i]};
}
$.extend(mergedData,arr);
arr.sort(function(a, b){
return (b['rel']-a['rel']);
});
});
var promise2 = $.getJSON("https://www.googleapis.com/freebase/v1/search?query="+$("#search").val()+"&limit=3&encode=html&callback=?",function(data){
console.log('data of second request', data);
var suggestion2="";
var arr = [];
for(var key in data.result){
arr[key] = {value : data.result[key].name, rel : data.result[key].score};
}
$.extend(mergedData,arr);
$("#suggest2").html(suggestion2);
});
$.when(promise1, promise2).then(function(){
mergedData.sort(function(a, b){
return (b['rel']-a['rel']);
});
var suggestion = '';
for(var key in mergedData){
suggestion+='<li>' + mergedData[key].value + ' ' + mergedData[key].rel + '</li>';
}
$("#suggest").html(suggestion);
});
});
});
Updated working jsfiddle : http://jsfiddle.net/rEPf3/13/

jQuery debug functionlity in a "class" file

im creating a simple game and, I need some direction for debuging some data.
i have a div in my HTML file, that I want him to show some data that change when some variables get change by the user actions.
for exmple i got var xPosition, I want to send the data to a div in the HTML, so i can see the current state of xPosition.
i realy dont have any idea where to start creating this functionlity.
my questions:
is it possible to create event inside this class and register some
element to him that will show all the changing data?
do i have to use a some a timer for that sort of thing?
this is the "class":
(function ($) {
$.Player = function (element) {
this.element = (element instanceof $) ? element : $(element);
this.movmentSpeed = 10;
this.size = $(element).width();
this.xPos = 0;
this.yPos = 0;
};
$.Player.prototype = {
//register events
InitEvents: function () {
var that = this;
$(document).keydown(function (e) {
var key = e.which;
if (key == 39) {
that.moveRight(400);
} else if (key == 37) {
that.moveLeft();
}
});
this.element.css({
left: this.xPos
});
},
//movment functions
moveRight: function (worldWidth) {
if ((this.xPos + this.size) <= worldWidth) {
this.xPos += this.movmentSpeed;
this.element.css("left", '+=' + this.movmentSpeed);
}
},
moveLeft: function () {
if (this.xPos > 0) {
this.xPos -= this.movmentSpeed;
this.element.css("left", '-=' + this.movmentSpeed);
}
}
};
} (jQuery));
here the HTML:
<div id="player">
<div id="debugData"> <div>
<script>
var player = new $.Player($("#player"));
player.InitEvents();
</script>
(sorry for my english)
jsFiddle Demo
I'd say having an internal function inside the Class would help. Maybe even having a setting where you turn the logging on by doing player.logging = true;, and having it default to false;
In your prototype just add a public prototype variable for logging = false, and our prototype function log().
The internal function you could use could be something as simple as:
logging : false, // our default
log : function (str) {
if (this.logging) {
$('#debugData').html(str);
}
},
This way you could leave your log(this.xPos); (or whatever you want to log) within your code, and by removing the player.logging = true; when you instantiate your class, they won't show up, till you put that code back in.

Categories