Wedge
Public area => The Pub => Off-topic => Topic started by: Suki on March 15th, 2013, 01:42 AM
-
OK, I found a nice script that pretty much handles mentions in an user friendly way: @username (it is better than what I had: {username}) the script is: h**p://ichord.github.com/At.js/
The downside is, it requires a previously declared javaScript array for the cript to search the names on, I'm currently using a func to query the database and returns a simple string like {1:'username', 2:'another username'} where the key is the users ID.
Then I pass this string to a JavaScript var by printing the actual string to be handled by the mention script:
$context['html_headers'] .= '
<script type="text/javascript"><!-- // --><![CDATA[
var breezeUsers = '. $tools->userMention() .';
// ]]></script>';
This works well, except that it would be a nightmare to print the string if a forum has a huge userbase, of course the query is limited to is_activated and posts > 10 but still it can grow to huge proportions.
What I was thinking is creating a simple SMF action, this action will return the string as a json object, I already had a class that handles all my ajax requests and returns the data as json so adding this wouldn't be an issue, the issue is that no matter how I fetch the string, the mention script doesn't recognize the string as a valid javascript array.
if I sent the data as a json object and use jQuery.parseJSON() on it it screws up the string.
I also tried to serve the response as a JavaScript file since I read that $ajax.() can call and execute javaScript files, however that didn't work either as $ajax.() didn't call the file (console.log told me that the file was fetched and it has a 200 status).
I wanted to use an ajax call because I can control the server response, I can use some cached entry as response and more importantly, I won't need to print a huge array.
The benefits of using this particular mention script is that it allows me to inject exactly what I want, it is triggered by typing @ or any other character but it can insert back to the textarea whatever you want, I set it up to inject this: @(username, ID) when an user selects a name from the names list now I have a nice and delimited string that can be parsed and converted to a link easily. No extra queries are needed :)
So, any help handling ajax request would be highly appreciated :) I just basically need a way to retrieve a valid javascript array/object via ajax but all my attempts had failed miserably. Oh, the mention script does support ajax calls, I followed all the exmaples on its doc section but it results in the same errors as my attempts, it doesn't recognize the serve response as a valid array.
-
When you use $.ajax, do you force a dataType?
Do you encode with json_encode()?
-
yep and yep
-
Does Firebug (yeah, whatever...) show a JSON tab when you click the requested file under Network?
-
More importantly, what's the Content-Type of the returned value?
IIRC jQuery.ajax() sniffs the Content-Type header to judge whether it's JSON or XML or whatever and if it isn't set to something indicating JSON, it assumes it's XML instead.
-
Don't have time to read it all... Hopefully I didn't misunderstand the question ;)
- Make sure you're not using jQuery 2.0 beta 1 (beta 2 is out, with its own problems too), as it's not correctly parsing data on the end (although it's mostly a problem with XML, I wouldn't trust that version with anything),
- Data received from $.ajax normally doesn't require parsing,
- Also ensure that you're sending the proper headers.
This is part of my code for Wedge... I've simplified it for your needs.
<?php
function returnAjax($json)
{
clean_output();
header('Content-Type: application/json; charset=UTF-8');
echo str_replace('\\/', '/', json_encode($json));
obExit(false);
}
Don't remember if clean_output() is part of Wedge or SMF, but it's not the point anyway ;)
-
OK, thanks for the replies, I'm using 1.9.1
This is the method I'm using to sent the response from the server: https://gist.github.com/MissAllSunday/5169914
I'll give this another try today, is json the more appropriate way to send the data back? I think the problem is that the server is sending this: "{1:'Suki', 2:'manzanita', }" instead of this: {1:'Suki', 2:'manzanita', } thus the mention script treats it like a string.
The mention script fires a bunch of callbacks that I cannot disable, this callbacks expect the data to be a valid js object/array
-
Yes, JSON is best. I've been through Hell and back again, and JSON is better than XML, however you view it. It's not better than a plain text response, but if you need multiple entries, obviously it's better :)
So, your server is returning double quotes around the string..? Very odd. I don't see anything that would cause that in your code. (You may want to use the more common 'echo' instead of 'print', though, but it's just a personal preference...)
Also, I'm surprised it would return an extra ',' before the closing }. I mean, this is something that would make it break in IE6 (more recent browsers don't have problems with it though.) And because JSON was created after IE6's release, I'd say they accounted for that. So... I don't really see how json_encode() could generate that.
You could also use a fallback json_encode, I removed that particular code from the sample I posted above to make it simpler for you, but what I do is test for function_exists('json_encode') (which has a 99.99% chance of being enabled in our setups), and if not found, it includes the PEAR version of json_encode, which works extremely well, albeit very slowly.
There's also this quick one: http://snipplr.com/view/13911.22389/
Which I fine-tuned into this:
function json_encode_fallback($v)
{
if ($v == null)
return 'null';
if (is_array($v))
{
// Non-associative array..?
if (!count($v) || array_keys($v) === range(0, count($v) - 1))
return '[' . join(',', array_map(__FUNCTION__, $v)) . ']';
foreach ($v as $k => $val)
$v[$k] = call_user_func(__FUNCTION__, $k) . ':' . call_user_func(__FUNCTION__, $val);
return '{' . join(',', $v) . '}';
}
return '"' . addslashes(preg_replace('/(\n|\r|\t)/i', '', strval($v))) . '"';
}
Please note, however, that I ended up using PEAR as fallback, instead of that, because it didn't generate exactly the same code, so it might have compatibility issues with jQuery's parser, too. You're never too careful...
-
OK, I uploaded the latest branch with the mention script implementation to my site, the url for fetching the json object is this one: http://missallsunday.com/index.php?action=breezeajax;sa=usersmention strangely enough, all the browsers I tested this url are receiving a php file, this is the only request that is sending a php file as a response as all the others are sending a json response. Could be a cache issue?, a server issue? im on LiteSpeed and sometimes it takes a while to pick up new pages specially if those pages are generated dynamically.
This is the code I'm currently using to send the ajax request and also firing the mention script:
jQuery(function(){
var breezeUsers = jQuery.ajax({
type: 'GET',
url: smf_scripturl + '?action=breezeajax;sa=usersmention',
data: '',
cache: false,
dataType: 'json',
success: function(html)
{
return html.data;
}
});
console.log(breezeUsers);
data = jQuery.map(breezeUsers, function(value, i) {
return {'id':i, 'name':value,};
});
jQuery('#content').atwho("@",{
tpl: "<li data-value='(${name}, ${id})'>${name} <small>${name}</small></li>",
'data': data,
'choose': "data-value",
'callbacks': false,
});
});
Now, both Opera drangonfly and firebug are telling me this error: name.toLowerCase is not a function and points out to the jquery.atwho.js file at line 6 in this particular code: https://gist.github.com/MissAllSunday/5172154
I'm not good with JS but as far as I know, filter is a callback (the script has many callbacks) that gets triggered by default and I don't understand javascript enough to see where the problem is.
I don't know if the problem is generated by my initial object or if the problem is somewhere else, if I hardcoded the var:
var breezeUers = {"1":"Suki","2":"manzanita"};
and pass that to the mention script it does work as intended that is why I assume the issue is on the data that is been sent from the browser or in the way I'm handling that data and pass it over to the mention script.
-
toLowerCase() cannot be used on a jQuery object. Try lower(), I think.
-
edited.
-
To avoid the toLowerCase crash, use...
if (name.toLowerCase && name.toLowerCase().indexOf(query) >= 0) {
Or, if you like 'clean code' that doesn't compress as well:
if ('toLowerCase' in name && name.toLowerCase().indexOf(query) >= 0) {
If name is not a string but a DOM element, get its class name first, or whatever text is associated with it, like $(name).attr('class').toLowerCase().
All in all, we have a problem: you're a rookie with JavaScript, and I'm close to what you could call an expert in that area.... But I don't have access to your full code and/or environment, and can't even begin with the basics. Thus, it'd take more time for me to fix the bug. And unless you're willing to pay, I don't really see any reasons to devote more than a few minutes to your problem. Don't take it wrong: I don't mind helping fellow developers, but as I understand it, you're writing a mod for SMF, it's competition, and I'd be shooting myself in the foot if there wasn't any compensation in it.
So I guess this is all I can do for you for now... :^^;:
-
Fair and reasonable!
-
OK thanks.
-
That was Suki's last post, so I guess she wasn't too thankful. Fair enough ;)
While I'm at it... One of the things I've been working on recently, is a rewrite to get rid of Xml.template.php. In order to do this, I wanted to have returnAjax handle things more gracefully, and in a more instinctive way. However, this requires a (small) rewrite that makes it sound like one of these hastily made PHP 'hacks', which I'm not sure we want in Wedge... There is, however, such a 'convenient function' in Wedge already, it's add_js(), where you can call multiple parameters and they'll be concatenated, so that existing inline JS can easily be transformed to use the function. It's neat, but it's a bit hackish.
So, right now, what returnAjax does is... Takes two parameters... A string and a type... Determines the type... If it's empty, it'll use a text/plain header, otherwise it'll use a MIME type that matches what we asked for, between text, XML and JSON.
Then it initializes the lot, and prints the string, and returns, making sure to bypass the template system but still go through ob_sessrewrite.
That's all good.
Except that if I want to send XML, it gets ugly quickly. The first thing I determined, is that since all XML responses have the <?xml...> header stuff in their content, I could add it automatically on the fly. Which I'm doing. But then I was thinking, doing this is ugly...
returnAjax('
<we>
<something />
</we>', 'xml');
Mostly because the 'xml' is at the end. I don't know, I just don't feel like doing that...
So, I wanted to refactor it to:
returnAjax('xml', '
<we>
<something />
</we>');
And consider that if we have only one parameter, it's a text string, and use $type as the string. And if we have two parameters, $type is the type, and the second parameter is the string. It suddenly makes it a hack...
Also, another thing I wanted to look into, was do things as in add_js, i.e. multiple parameters are concatenated into a single string, allowing for easy conversion of existing echos.
But then it means that the ($type, $string = '') hack is no longer possible, because I could very well be doing returnAjax('xml', ' is something I hate'), and thus Wedge would consider this to be a XML string, instead of a text string split in two... Yes, it's unlikely to happen, but it just feels wrong.
So... Do I just leave the function as it is right now, or... Do something else..?
-
Gee I hope I didn't tread on anyone's toes here, my meaning was Nao's suggestion was fair and reasonable. Not intended as a slight on Suki...Apologies for the misunderstanding.
-
OK thanks, means OK thanks, as far as I understand thanks means I'm thankful on the help provided here.
I don't know what else do I need to say? You don't want to help me, fair enough, thats why I said thanks and locked the topic to prevent more people inserting their opinions on whether or not they find it fair, its a shame the lock wasn't respected.
-
After years of maintaining and developing forums, I've learned to determine when someone is getting annoyed and is going to 'retire' their account, that's all I'm saying ;)
PS: I posted here because it was on-topic with what I had to say yesterday. By locking the topic again, you're preventing regular people from giving their opinion on my AJAX tweaks.
-
Yup, I specifically unlocked it the first time so that people could comment on Nao's proposals.
-
(And I didn't notice the original lock, apologies Pete.)
-
I already said thanks, I understood your reasons and said thanks, I honestly don't know what else do you want from me or why do you think I wasn't been grateful... It does bother me the fact that I always said thanks for the help received here and yet you post a month later saying I wasn't...
As for me "retiring" I've been login here fairly often and I've been reading most if not all the post and topics since then, me not posting doesn't mean anything (it means I do not have anything to add to any topic posted here) so please do not make wrong assumptions and specially do not make false impressions of me not being thankful and grateful for your help just because I didn't posted anymore, that was just a coincidence if anything.
As for how much on topic this was, I dunno, you want to re-write some template, thats far from what I wanted to do, as far as I know you have specific boards for Wedge features/discussions, this was a generic jQuery problem that has nothing to do with whatever approach you're doing for Wedge.
I respectfully request for the lock to stay in place to avoid people to keep posting about my issue (or any other topic derivate of it) and instead create a new topic on whatever board it fits the most where people can only focused on your ideas. Or at least do not jump to wrong conclusions about my lack of posting here.
Thanks.
-
I already said thanks, I understood your reasons and said thanks, I honestly don't know what else do you want from me or why do you think I wasn't been grateful... It does bother me the fact that I always said thanks for the help received here and yet you post a month later saying I wasn't...
No, it's not that -- I really don't have time to look into old topics... Heck, there are still dozens (hundreds?) of topics I have yet to read for the first time... I simply did a search on 'returnAjax', so as not to open a new topic for something I remembered I'd discussed before, and found your topic... So I replied to it, and also mentioned that the fact that your last post was that particular one (and you hadn't posted in weeks), pretty much implied that the 'thanks' was along the lines of 'thanks for all the fish', if you know what I mean.... ;)
There's nothing else to be found in my post...As for me "retiring" I've been login here fairly often and I've been reading most if not all the post and topics since then,
Yes, I know, when I posted, your last login date was April 6, so you'd just gone back into lurking mode, and I just...
Oh, crap, I'm falling into my own trap, and I'll just repeat myself over and over. Let's not waste on this, all right? I'd rather work on Wedge than have to explain myself... :-/
-
The post above refuses to get 'read'... I can refresh the page all I want, it always says 'New' in this topic, and on the homepage...
VERY, very strange.
Note that I quick-edited it once.
:edit: Once my reply was posted, it fixed itself. Also, my new reply wasn't marked as 'New' in this topic. I guess it really only happens when quick-editing...
:edit: This quick-edit persisted the 'New' state for two refreshes. After the third one, it was back to normal. Still, the previous post -- after 4 or 5 refreshes it was still retaining its unread flag...
:edit: Second quick-edit worked as expected, i.e. no 'Unread' flag anywhere, including in the homepage... Oh, my! That's very interesting...
-
So I replied to it, and also mentioned that the fact that your last post was that particular one (and you hadn't posted in weeks), pretty much implied that the 'thanks' was along the lines of 'thanks for all the fish', if you know what I mean.... ;)
There's nothing else to be found in my post...
.___. then why the mention about me not been grateful ??? that is what bothers me... there is no "thanks for the fish" or whatever you call it, it is a simple and mere "thanks" meaning "thank you"... There's nothing else to be found in my post...
I don't know what do I need to do to you realize my thanks are just that, simple thanks, nothing more. nothing was implied there, I locked the topic because there was nothing else to discuss and no one else were going to help me, thus, the topic being open was pretty much pointless and the only possible way to go was to keep discussing your reasons for not helping me, something I certainly wasn't interested on discuss since I understood your reasons in the first place and thanked you already.
It is I the one that is repeating myself, I already said thanks as many times as it can be said without losing its meaning, again I do not know what else do you want.
Been in lurking mode is a bad thing here? I don't know about you but I just don't post on any topic for the sake of posting, also, I'm not here 24/7, I usually enter here from my phone, do check the main page and if there is an interesting topic I read it, if I have something to say, I say it, if not I left the site as simple as that.
I posted looking for help here because I felt sufficiently confident in actually asking for help from you guys, I realized that was a mistake, I recognized your reasons, I thanked you and all the people who helped me and that was it, I went back to my old routine of checking the site, I honestly don't know how that can be misinterpreted in any way... I actually have been talking to Arantor and never ever told him about this topic or anything related to your response or me been mad because of your response because there is no issue with it.
So please, once again, do not misinterpret my posting or actions or the lack thereof.
And once again, there is no "thanks for the fish", "ungratefulness", "unfriendliness" or any other bad action on my part. Thank you, means thank you.
If you do not want to waste time on this then I suggest you to accept the fact that I was thanking you and nothing else, do not look for any issues where there is none.