Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Fruit Smoothies
Mar 28, 2004

The bat with a ZING
Hey. I have an XML request which gives me a list of data. An older version of these data already exist on the webpage. Both data are variants on a simple list. What's the best way of syncing these lists? In the HTML list, each item is in its own div, and the XML nodes from the new list are being looped through.
The method I can think of at the moment, is to remove all old (HTML) items from the new (XML) list. If an item isn't found in the XML list, it's removed from the HTML. At the end, all the remaining items in the XML are added to the HTML div list.
This poses data structure problems, and I'm not familiar with how best to handle lists in javascript. Would arrays be the way forward?

Adbot
ADBOT LOVES YOU

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

Supervillin posted:

Performance-wise it seems like it would be much faster to just replace the whole list than to sync using two or possibly three loops through each set. Maybe I'm too tired or something, but wouldn't you get the same data if you destroy the HTML list and add all the XML items?

Edit: If I DID misunderstand, either Arrays or object literals should work fine. Those are pretty much the only list paradigms built into JavaScript. I know ExtJS and probably some other libraries have ways of binding data sets together, might be what you need.

The trouble is, there are other elements tree'd under the list items. These contain forms and images which empty and flicker if the HTML is re-written. The list updates about every second.

Fruit Smoothies
Mar 28, 2004

The bat with a ZING
I'm building a class on top of JQuery's $.ajax class. My JSON has a response code that determines which function to call back.

code:

function Ajax() {

	var AJAX = this;

	var responseFunction = function(jQueryAjaxSuccessResponse) {
		
		switch(jQueryAjaxSuccessResponse.type) {

			case "OK": {
				// call the "OK" function
				// This is where AJAX is the window object.
				okFunction(jQueryAjaxSuccessResponse, AJAX]);
				break;
			}
			case "WARNING": {}
			...	

	}

}

How can I pass the AJAX object to the callback? I've stepped through the code, and "this" is always either the window or the jQuery javascript object!

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

Gordon Cole posted:

What are you expecting it to be? The Ajax function? The 'this' keyword refers to the object that contains the function, not the function itself. If you're defining the Ajax function in the global scope then 'this' will refer to the window object.

You can try just passing in Ajax instead of AJAX, I suppose, though it would probably be better to rethink how you're organizing your code. It's best to avoid working in the global scope entirely. You could try putting your function into your own object, so you would then be able to access it via this.Ajax.

If it was any other object than "Ajax" I could probably re-organise it into my other classes. The trouble is, every ajax request is called this way throughout the code, and sometimes the response function needs to call Ajax().request() which effectively submits the request again.

Any other ideas?

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

Gordon Cole posted:

I'm having a hard time understanding what you're trying to do here and what the problem is. It looks like you're defining the Ajax function in the global scope (on the window object), meaning anything in your program can already access it, but you're also trying to pass it into a callback function. If they can already access the function globally why do they need to get it passed back to them?

Why are you wrapping jQuery's ajax function in the first place?

There are multiple instances of the object. I'm wrapping it because it contains a lot of error handling code that goes beyond simply assigning a standard error handling function; and it allows me to more easily load multiple URLs and keep track of them etc.

There are also many instances where the Ajax object is created within other classes. The issue is that I need my response function to be able to access the Ajax object that called it. At the moment I'm trying to avoid doing this:

JavaScript code:
function Ajax() {
	var self;
	
	this.setSelf = function(obj) {
		self = obj;
	}
	
	var callback = function(response) {
		okCallback(response,self);
		
	}
}

var instance = new Ajax();
instance.setSelf(instance);
It looks horribly messy. I have literally no idea why they adopted the syntax "this.param" within a class is "this" is evaluated to be the parent, rather than "self"

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

Suspicious Dish posted:

What? That's not it at all. Basically, if you call o.f(), o is passed as the this object. If you do var f = o.f; f();, the global environment object is passed (window in a browser context). Closures are not automatically created.

Function.prototype.bind is a way around this.

But ultimately the response function is always going to call the callback is going to be the $.ajax object. This is why I was trying to store it before hand within the object, so it could get passed.

From what I know about prototypes; they're meant to be the default value / function if it's not specified within a specific instance of the class.

Fruit Smoothies
Mar 28, 2004

The bat with a ZING
You'll LOVE this... I wrote "var thing = Ajax()" rather than "var thing = new Ajax()" which made "this" evaluate as the window, rather than "self" within the object. Thanks for your help though, guys.

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

TildeATH posted:

code:
function foo() {
    console.log("I want this function to work.")
    event.target.stopPropagation() //Here?
}

function bar() {
    console.log("If you can read this, just shoot yourself, it's the easy way out."
}

Just in case you missed it, you are doing this?

code:
function foo(event) {
...
}

Fruit Smoothies
Mar 28, 2004

The bat with a ZING
I'm just looking into framework programming - specifically Laravel, but I am crap at organising Javascript. Are there any tutorials or advice for separating JS code?

Organising the AJAX side of things is easy, since it basically mirrors the API structure. However, the javascript that controls functionality involving manipulating HTML has ended up being an icky mass of numbers of anonymous functions and strings of HTML.

Any advice on getting tidy, and organising page-unique HTML rendering into a more readable, less horrific format?

(Basically I need a way of linking templated HTML to the AJAX without messy event functions. Updating the HTML is the messiest bit!)

Fruit Smoothies
Mar 28, 2004

The bat with a ZING
I need a textarea with bold support, so I'm using a div with contenteditable. Unfortunately, I need to manipulate what's being entered. At the moment, I'm starting with this

code:
<div contenteditable="true">
	<b>Hello</b><br/>
	World.
</div>
The idea is to replace all the <b> tags with <i> tags. The problem is dealing with the cursor position, as every time the html is altered, it returns to the beginning.
My method, therefore, is as follows:

1) On keypress, setTimeout to the tag replace function to allow the element to accept the keypress event.
2) the timeout function gets the cursor position, makes the html changes, and then reinstates the cursor position.
However, in this code, the element loses focus afterwards and afaik, the cursor position is ignored.

code:
$(element).keypress(function() {
	var range = document.createRange();
	setTimeout(function() {
		var sel = window.getSelection();
		var current = $(element).html();
		var bPos = current.indexOf("<b>");
		var bePos = current.indexOf("</b>");
		//while(bPos >= 0) {
			current = current.replace("<b>", "<i>");
			bPos = current.indexOf("<b>");

		//}
		//while(bePos >= 0) {
			current = current.replace("</b>", "</i>");
			var bePos = current.indexOf("</b>");
		//}
		$(element).html(current);
		// range.collapse(true);
		sel.removeAllRanges();
		sel.addRange(range);
		$(element).focus();
	}, 10);
});
Any help would be much appreciated :)

Fruit Smoothies
Mar 28, 2004

The bat with a ZING
This is a Vue.js framework question, so I understand this may not be the perfect thread for it. I am having issues with the scoping of slots.
Here's a simple list example. Most Vue tutorials will end up with the HTML on your main page looking like this (pre-render)

code:
	<div>
		<list-component></list-component>
	</div>
Which I absolutely despise because it gives you too little information about the construction of the list! My goal is to create

code:
	<div>
		<list-component>
			<list-item v-for:"item in items">
				{{item.name}}
			</item>
		</list-component>
	</div>
The problem here is the <slot> in list-component's template. This slot (which contains <list-item>) has NO context about the "items" data because the slot is rendered outside the parent's scope. There is documentation on this phenomenon here but it's not especially clear documentation!

Before I give up and conform to the ridiculously vague top example, can anyone offer any help here?

Fruit Smoothies
Mar 28, 2004

The bat with a ZING
JavaScript code:
	async add(func) {
		await Promise.all(this.list);
		let promise = new Promise(async (done,fail) => {
			try {
				await func();
				done();
			} catch(e) {
				fail();
			}
		});
		this.list.push(promise);
	}
Usage is meant to be:

JavaScript code:
obj.add(async () => {
	await thing();
	await otherThing();
});
But they aren't executed in order and I have no idea why.

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

Doom Mathematic posted:

Actually I think you might be able to get away with eliminating that whole wrapping Promise and just writing this.list.push(func());?

That is much simpler, but it doesn't solve the underlying issue sadly. It waits for the first promise, but not subsequent ones.

Fruit Smoothies
Mar 28, 2004

The bat with a ZING
Edit: Stil having issues

Adbot
ADBOT LOVES YOU

Fruit Smoothies
Mar 28, 2004

The bat with a ZING

necrotic posted:

Are you calling this as await obj.add or just plain obj.add? The latter won't work here, calling an async function spawns a new promise and if you do not wait on that promise it may not be invoked before the next time you call obj.add.

I'm not awaiting because add() is typically an event-emitted callback. I have given up and I'm now using an npm package called easy-promise-queue. Thanks though

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply