I'm working with Solr 4.3.0 and implementing Ajax-Solr for the interface. However, Ajax-Solr does not save state automatically. There is a ParameterStore and ParameterHashStore method but they don't work with legacy browsers. I used my google-fu and found the following but it doesn't work as intended:
https://github.com/evolvingweb/ajax-solr/pull/23
...with a few more resources I came up with this:
<script>
var Manager;
(function ($) {
Manager.setStore(new AjaxSolr.ParameterHashStore());
Manager.store.exposed = [ 'fq', 'q', 'start' ];
Manager.init();
// Establish Variables
var History = window.History; // Note: We are using a capital H instead of a lower h
if ( !History.enabled ) {
// History.js is disabled for this browser.
// This is because we can optionally choose to support HTML4 browsers or not.
return false;
}
State = History.getState(),
// Bind to State Change
History.Adapter.bind(window,'statechange',function(){ // Note: We are using
statechange instead of popstate
// Log the State
var State = History.getState(); // Note: We are using History.getState() instead
of event.state
History.log('statechange:', State.data, State.title, State.url);
});
// Log Initial State
History.log('initial:', State.data, State.title, State.url);
})(jQuery);
</script>
But it doesn't work. The Forward and Back buttons are broken in all browsers and nothing gets logged to the console.
What am I missing or is v4.3.0 inherently borked right now and needs a patch?
Would greatly appreciate any help. Thank you!
I know nothing about AJAX-Solr. But I think discussing some few things with you might help.
If AJAX-Solr works the same way the normal AJAX do, then AJAX-Solr will execute some server-side function and outputs it in client-side (of course without refreshing the actual page). As consequence, you should put the function triggering the ajax call inside your History.Adapter.bind(window,'statechange',function().
About State = History.getState(); it is responsible of returning the state data of a pushed state in history stack (url, title, ajax parameters). please to read the doc about hisrory.js on github. Note also that you are using a comma instead of semicolon in your code. In addition, you are calling this function twice. Call it only one time inside your Bind function to get the state parameters and use them in your ajax call (in order to refresh the part of your page while navigating over brower back-forward buttons).
I advise you to read also Back-Forward buttons of browser are showing weird behaviour. History.js, maybe it will help you understand positionning of ajax regarding Bind.
Good luck.
Related
We have a use case where we need to block Drupal's core ajax error handling from alerting users (we're handling the error reporting on our own). Previously another developer had commented out a line in the core ajax.js file, to prevent Drupal from spawning the alert box, but I'd like to handle it without touching core.
From the core, drupal.js:
/**
* Displays a JavaScript error from an Ajax response when appropriate to do so.
*/
Drupal.displayAjaxError = function (message) {
// Skip displaying the message if the user deliberately aborted (for example,
// by reloading the page or navigating to a different page) while the Ajax
// request was still ongoing. See, for example, the discussion at
// http://stackoverflow.com/questions/699941/handle-ajax-error-when-a-user-
// clicks-refresh.
if (!Drupal.beforeUnloadCalled) {
alert(message);
}
};
My current fix, is to override the Drupal.displayAjaxError function and change the Drupal.beforeUnloadCalled property that determines whether or not to alert the error:
var ajax_error_backup = Drupal.displayAjaxError;
Drupal.displayAjaxError = function (message) {
Drupal.beforeUnloadCalled = true;
ajax_error_backup(message);
};
My question, is whether or not this is an appropriate fix? I know that I could also override the function and just leave it empty - costing fewer lines, and not invoking another call to the original function (and saving the object I've created by backing up the original in ajax_error_backup).
Am I adding complexity to keep things tidy, or should I just override with:
Drupal.displayAjaxError = function (message) {
//empty
};
To clarify - the desire is to never have this ajax alert occur, so there's not functional difference between my desire to keep things neat/tidy, and just overriding the function with a blank one - there isn't a case where want this alert to succeed.
Thanks in advance for helping this old dog think through something with fresh eyes.
In this case, there isn't one option that seems to be clearly better than the other. It should be handled on a case by case basis, and in this case, either of the methods really is adequate.
I personally opted for using the slightly more expensive method of overriding the function and calling it back, because I felt that it might be somewhat more future-proof:
var ajax_error_backup = Drupal.displayAjaxError;
Drupal.displayAjaxError = function (message) {
Drupal.beforeUnloadCalled = true;
ajax_error_backup(message);
};
If Drupal were to extend the function on their end in the future, there might be another condition that we wouldn't want to override.
Overriding with the empty function would be the cheapest, but would also potentially be a bit heavy handed.
It seems that either approach is valid, and is probably best handled case-by-case.
I've come across some weird behavior in IE11 when it comes to overriding functions in javascript.
On a webpage i have the following code:
(function ()
{
var tempSetItem = window.localStorage.setItem;
window.localStorage.setItem = function (key, data)
{
var newdata = JSON.stringify(data);
newdata = JSON.parse(newdata);
newdata.CachedDate = new Date();
tempSetItem.call(window.localStorage, key, JSON.stringify(newdata));
};
})();
This should simply override the localStorage.setItem() function.
However, i ran into some trouble with the code and decided to comment it out.
When i refreshed the page (cleared cache ofcourse) the same problem was still there.
I soon realised that IE had somehow cached my override.
I searched through all my files to make sure i didn't override it anywhere else and i even tried to set it to null manually through the console (In other words, it should not be null after a refresh) and after a refresh, it was now null.
It seems to be cached per domain or per URL in some way and i don't know how to clear this cache or if it's even possible.
I even tried repairing IE but localStorage.setItem is still null on my webpage.
I still don't know why the overriding gets cached but i found a way to reset it.
Calling localStorage.clear() resets the entire localStorage-object, including the setItem-function.
To avoid the rest of the problem i simply made a normal wrapper-function instead of overriding the original and called that from all the places where i would otherwise call localStorage.setItem().
Solution below: Edit #2
I've a HTML-list the user is able to sort. I don't want to save the data after every drag/drop action, so I save the data on unload: in a cookie and database. Thats working, but:
After saving the data the list is hidden and I get a "syntax error" in this line:
<!DOCTYPE html>
It's strange because everything works fine after refreshing the same page (F5) without changing anything.
I try to find the cause but no success. That's the flow:
1. visit the page (index.php)
2. change the list (set: list_is_dirty = true)
3. click any internal link (call $(window).unload( ... save_data() ... )
4. target page appears without the list (syntax error!)
5. refreshing the page (everything works fine)
Do you have any idea how to find this error? Any tools or strategies? Or maybe the same experience with the unload function?
Thanks in advance!
Edit:
Some code:
var list_is_dirty = false;
// document ready?
$(function() {
function sort_list() {
// some code, not important
}
sort_list();
$(window).unload(function() {
if (list_is_dirty == true) {
/* ---------- HERE's the error! ---------- */
/* The error occures when I try to call the script.php
I tried load(), $.post(), $.get() but nothing works.
The string is correct. I'm not even able to call any of
these functions without params.
*/
// send data to script.php to save data
$("#div").load("script.php?str="+list_data_str);
$.cookie("list_data", list_data_str);
}
});
}
Edit #2 / Solution:
I don't know why, but everything works with window.onbeforeunload instead of jQuery.unload(). An explaination would be great! I'm sorry for this confusing thread!
window.onbeforeunload = function(e) {
$("#div").load("script.php");
}
I think that your issue is with: list_data_str as it's not defined anywhere.
if you are trying to say that you want to do AJAX post for example, then obviously you need to look for success event
else it appears that what your demo code is missing something because you can do it the way you are trying if at the receiving script you use $_GET over the URL and not pay attention to any parameters.. In other words, you are missing the object and when you refresh the page it's loaded into the DOM. Apparently that could be the issue that you are describing, I would suggest that you post a bit more of relevant to your issue code.. like the receiving script or any errors from a debugger like Firebug.
Regarding how to test it, you might want to use console.log in supported browsers or simply alert when is setting up the cookie.
var global list_is_dirty = false;
function sort_list(list, list_is_dirty) {
// some code, not important
//check the list and the flag
//you should return a value, else it does not make sense to use a function here.. note the var defined as global
return list; //?? not sure what to return as don't know what this code does from the posting
}
jQuery(function($)
{
$(window).load(function(e){
var list_data_str= sort_list( );
// send data to script.php to save data
e("#div").load('script.php?str='+list_data_str);
//on unload destroy the cookie perhaps?? or if it's not set a session variable
e.cookie("list_data", list_data_str);
...
The unload event
$(window).unload(function(e) {
$("#div").load("script.php?str="+list_data_str);
$.cookie("list_data", list_data_str);
}
});
}
....
// About your EDIT: Are you passing in here any parameters to the script? Because I think the problem is at that logic.
window.onbeforeunload = function(e) {
$("#div").load("script.php");
I have a dojo button bar which is bound to a csjs function. This function does a partialrefreshget() on a datable control. The datatable control contains a view as its datasource.
In the this.keys property I have defined some logic to see if the partialrefresh was triggered by checking for the context.getSubmittedValue(). While experimenting with this technique I noticed that the following code is triggered twice.
<xp:this.keys><![CDATA[#{javascript:
var vec = new java.util.Vector()
vec.add("category");
if(context.getSubmittedValue()!=null){
var x = context.getSubmittedValue().trim();
print("--")
}
return vec;}]]></xp:this.keys>
the print statement is printed twice to the console and the logic is therefore triggered twice. Can someone explain to me why this happens and what I can do about it? Should i check for submittedvalues somewhere else or?
I think if you implement a phase listener to print out each phase step, you'll see that this.keys is evaluated twice during the LifeCycle. Probably once during Render Response, and the other during Restore View or something. I would avoid putting application logic within property calculations as it can be triggered at times you would not think it should be unless you are very in tuned with the application lifecycle.
I actually see the submit two or three times on some controls. I have heard that it is an anomalie in the JSP engine that has not been resolved.
What I do is write the vec to a request scope variable after it is computed. then add logic before it is computed to fetch the request scope variable and if it exisits, return it instead of recomputing the value.
After a bit of testing i gave up calling my own partialrefreshget method.the extlib dojo toolbar contains a onclick event which is triggerd when on a node the submitvalue is set. In this onclik event i added code like
Var v = context.getsubmittedvaleu();
If("action".equals(v)){
// do stuff that changes the dataset..
}
The event handler is set to partial refresh a datatable wich receives the new data. This is a much cleaner implementation than checking the submittedvalue in the datasource ( as stated by (jeremy hodge).
This way the datasource is only refreshed once.
As a sidenote i would like add that it would be nice to add such an event directly to the treenode(s) as I would do in standard java swing /awt dev by adding a controllistener to a button.
I am using IsDirty to check for changes in my FCKeditor. Unfortunately, it seems that its functions are asynchronous.
Here is the failing code:
var txtObj = $('activities').EstActText1.id;
var oEditor = FCKeditorAPI.GetInstance(txtObj);
oEditor.SetHTML(jsonObj.DATA.ESTACTTEXT1.toString());
oEditor.ResetIsDirty();
The problem is, SetHTML does not take effect immediately (if you put a check right afterward using GetHTML, it will return what was previously in the textarea). Thus, ResetIsDirty will run, THEN the HTML will actually be changed, and the dirty flag will be set again.
Is there any way I can force the SetHTML call to complete before continuing? If not, is there any way (besides a ghetto setTimeout call that will add latency and not necessarily always work) to make sure that the ResetIsDirty will actually take effect after the HTML is changed?
I still would be interested in a direct answer, but I'm leaning on the side of that not being very feasible. It would require something of a sleep function, but JavaScript doesn't go toward that realm.
However, what you're supposed to do is handle the FCKeditor_OnComplete event:
function FCKeditor_OnComplete( editorInstance )
{
editorInstance.Events.AttachEvent( 'OnAfterSetHTML', function(){
editorInstance.ResetIsDirty(); // clean flag to avoid having to save
} ) ;
editorInstance.ResetIsDirty(); //clean flag upon initial load as well
}
This was placed in a script tag with defer set.
I know, the question is not actual, but it may be useful to someone. Try to use:
ckeditor = CKEDITOR.instances['Editor_ID'];
ckeditor.setData(lyr_data.lyrics,function(){
ckeditor.updateElement();
ckeditor.resetDirty();
});