I open a window using javascript window.open()
The window that opens has the following code:
jQuery(document).ready(function(){
jQuery("#lang").change(function(){
var lname = jQuery(this).val().split("-");
window.location = '<?php echo JURI::root();?>index.php?lang='+lname[0];
alert(lname[0]);
alert('lang '+lang);
});
Now this code is triggered upon 'lang' select menu change. I open the window programmatically using window.open and I managed to populate data into the window fields using Window.executeScript(). For example this works for me:
loginWindow.executeScript({
code: "jQuery('input#username').val('10500050')"
});
However, when I tried to follow the same logic for changing the selected item in selectMenu called 'lang' for the same window, I failed.
Attempts
I tried all the following lines in executeScript;
code: "$('#lang').val('ms')"
code: "jQuery('#lang option[value=ms]').prop('selected', true)"
code: "jQuery('#lang').selectmenu('value', 'ms')"
with these in the next executeScript to trigger change
code: "$('#lang').trigger('change')"
code: "$('#lang').selectmenu('refresh', true)"
code: "jQuery('#lang').selectmenu('refresh')"
code: "jQuery('#lang').selectmenu('change')"
code: "$('#lang').change()"
None of them helped. I'm not sure if I should combine them in one executeScript. I do not know how to do that. The window that opens is from different domain.
Am I missing something here?
The entire code on the opener side is as follows:
loginWindow.addEventListener( 'loadstop', function() {
alert('test');
var loop = setInterval(function() {
loginWindow.executeScript({
code: "jQuery('input#username').val('10500050')"
},
function( values ) {
var give = values[ 0 ];
if ( give ) {
clearInterval( loop );
giveMeUsername();
}
});
loginWindow.executeScript({
code: " jQuery('input#name').val('10500050')"
},
function( values ) {
var give = values[ 0 ];
if ( give ) {
clearInterval( loop );
giveMeUsername();
}
});
loginWindow.executeScript({
//code: "$('#lang').val('zh')"
//code: "jQuery('#lang option[value=ms]').prop('selected', true)"
code: "jQuery('#lang').selectmenu('value', 'ms')"
//code: "localStorage.setItem( 'lan', 'ms' )"
},
function( values ) {
var give = values[ 0 ];
if ( give ) {
clearInterval( loop );
giveMeUsername();
}
});
loginWindow.executeScript({
//code: "$('#lang').trigger('change')"
//code: "$('#lang').selectmenu('refresh', true)"
//code: "jQuery('#lang').selectmenu('refresh')"
//code: "jQuery('#lang').selectmenu('change')"
code: "$('#lang').change()"
},
function( values ) {
var give = values[ 0 ];
if ( give ) {
clearInterval( loop );
giveMeUsername();
}
});
});
});
The first two executeScript work fine. But the last two (selectMenu part) do not work. Nothing occurs.
UPDATE
When add this code to the window itself, it works and the select box value is changed:
jQuery("#lang option[value='zh-TW']").attr("selected","selected");
jQuery('#lang').change();
However, when I add it inside executeScript in the parent window (opener), it does not work!
As the code works when I paste it directly in the child window inside jQuery(document).ready(function(), I assumed it should work from the parent window using executeScript. After many trial and error experiments, the following code worked for me:
loginWindow.executeScript(
{
code: "jQuery('#lang option[value=zh-TW]').attr('selected','selected'), jQuery('#lang').change()"
});
Which is the same code I mentioned in "Update" part of my question, except the difference in single quote and double quote. Here using executeScript, I had to manipulate to use double quote only to enclose the entire injected code, the rest I use single quote.
The code above, change the option selected in select box in child window using executeScript method in parent window (opener).
Related
I'm using introjs to build a tour of my application. I've searched in quite a few places online and through the documentation but can't seem to find anywhere a method of how to run a function upon skipping or clicking done on the tour. I'm trying to make it so a cookie is stored and the tour isn't run again until a user requests it or a new user comes to the site. Any help would be great, thanks!
$(function(){
var introguide = introJs();
introguide.setOptions({
showProgress: true,
steps: [
{ hidden }
]
});
introguide.start();
});
This code allows to store the tour info
var introguide = introJs();
window.addEventListener('load', function () {
var doneTour = localStorage.getItem('MyTour') === 'Completed';
if (doneTour) {
return;
}
else {
introguide.start()
introguide.oncomplete(function () {
localStorage.setItem('MyTour', 'Completed');
});
introguide.onexit(function () {
localStorage.setItem('MyTour', 'Completed');
});
}
});
Yes, there is a way but with some caveats.
First, after intro.js is loaded you will have a global called introJs with a property fn (standard jquery plug-in approach).
By setting a function using the oncomplete() function under introJS.fn, you can perform some actions when the user hits the 'Done' button.
Here's an example that just displays a console message:
introJs.fn.oncomplete(function() { console.log("Finished"); });
This works as expected. You can put this in a script anytime after the intro.js library is included.
The 'skip' button functionality, however, will only call the 'oncomplete' handler if you are on the last step. The author of the code views that as not complete and so doesn't run that code as you can see by this extract from the code:
skipTooltipButton.onclick = function() {
if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') {
self._introCompleteCallback.call(self);
}
_exitIntro.call(self, self._targetElement);
};
This basically says it must be at the last step for this to consider calling the complete callback.
Of course, you could fork the code and remove the restriction. I would suggest if you are going to do that, create a _introSkipCallback in a fashion similar to _introlCompleteCallback and invoke that unless on last step where you might invoke both functions if present.
Hope this helps.
Use oncomplete for functions after 'Done' is clicked
Use onexit for functions after 'Skip' is clicked
Bonus function: onchange will log each step, this can be used to call functions on a particular step
document.getElementById('startButton').onclick = function() {
// log each step
introJs().onchange(function(targetElement) {
console.log(this._currentStep)
if (this._currentStep === 3){
stepThreeFunc()
}
}).start()
// clicking 'Done'
.oncomplete(function(){
someFunc()
})
// clicking 'Skip'
.onexit(function(){
someOtherFunc()
});
};
I've noticed that onexit will be called when you click the done button (which is skip until the last step). onexit does not appear to bind this to the introjs object, so I was able to solve the issue of having onexit called when the walkthrough was completed like this:
// during setup
introJs.oncomplete(handleOnComplete);
introJs.onexit(() => handleOnExit(introJs));
function handleOnComplete() {
console.log(this._currentStep); // this is bound to the introJs object
}
function handleOnExit(introJs) {
const currentStep = introJs._currentStep;
if (currentStep < introJs._options.steps.length) {
doSomethingOnSkip();
}
};
I was going to add a comment, but my rep is too low. I didn't want to answer because I haven't actually tested this, but in version 2.5.0 (maybe previous versions too), there is the onexit function, which I believe is supposed to handle interrupts as well as clicking done at the end. Did you try that?
if ($(".introjs-skipbutton").is(":visible")) {
$( document ).on('click', '.introjs-skipbutton', function(event) {
event.stopPropagation();
event.stopImmediatePropagation();
self.exitTourguide();
});
}
I am using introJS tool in my application to give tour guide information of my application.
I used some functions for handling it dynamically. Here stepsData sending in an array format.
var intro = introJs();
intro.setOptions( {
'nextLabel': 'Next >',
'prevLabel': '< Back',
'tooltipPosition': 'right',
steps: this.stepsData,
showBullets: false,
showButtons: true,
exitOnOverlayClick: false,
keyboardNavigation: true,
} );
hope it will help for handling skip button action.
var self = this; intro.start().onbeforechange( function() { /* skip action*/
if ( $( ".introjs-skipbutton" ).is( ":visible" ) ) {
$( document ).on( 'click', '.introjs-skipbutton', function( event ) {
self.exitTourguide();
});
}
});
skip and done action handling.
/Done click action/
intro.oncomplete( function(){ if ( $( ".introjs-skipbutton" ).is( ":visible" ) ) { $( document ).on( 'click', '.introjs-skipbutton', function( event ) { event.stopPropagation(); event.stopImmediatePropagation(); self.exitTourguide(); }); } });
/* clicking 'Skip' action */ intro.onexit(function(){ if ( $( ".introjs-skipbutton" ).is( ":visible" ) ) { $( document ).on( 'click', '.introjs-skipbutton', function( event ) { event.stopPropagation(); event.stopImmediatePropagation(); self.exitTourguide(); }); } });
I have seen what looks like it could be the solution to this issue in other questions on stackoverflow, but NONE of them have worked.
I am trying to get the innertext of the link that was clicked to open Fancybox:
$("a.turnDateLink").each(function() {
var that = $(this);
$( "a.turnDateLink" ).fancybox({
'type': 'modal',
'onComplete': function() {
var currentday = $(that).text();
console.log(currentday);
},
'afterClose': clearCurrentDay,
'fullScreen' : false
});
});
It only returns the innerText of the last a.turnDateLink. EVERY TIME! ugh.
Keep in mind that I would like to use the fancybox grouping with this.
See the Fancybox documentation to understand grouping: http://fancyapps.com/fancybox/3/docs/#usage
If you have a group of items, you can use the same attribute
data-fancybox value for each of them to create a gallery. Each group
should have a unique value:
Check documentation about events - http://fancyapps.com/fancybox/3/docs/#events
The first examaple contains useful tips, including how to find clicked element:
onComplete: function( instance, slide ) {
// Tip: Each event passes useful information within the event object:
// Object containing references to interface elements
// (background, buttons, caption, etc)
// console.info( instance.$refs );
// Current slide options
// console.info( slide.opts );
// Clicked element
// console.info( slide.opts.$orig );
// Reference to DOM element of the slide
// console.info( slide.$slide );
}
Try like this.Change $( "a.turnDateLink" ) to that.
$("a.turnDateLink").each(function() {
var that = $(this);
that.fancybox({
'type': 'modal',
'onComplete': function() {
$("#currentday").html('');
var currentday = that.text();
console.log(currentday);
},
'afterClose': clearCurrentDay,
'fullScreen' : false
});
});
i try to do something like a status-check to enable/ disable settings.
// file 1
function settings( valStatus ){
var status = valStatus;
this.getStatus = function(){
return status;
}
this.setStatus = function( valStatus ){
status = valStatus;
}
}
calling this function here:
// file 2
$settings = new settings( false );
$(document).ready(function() {
$( '#openSettings' ).on('click', function() {
$settings.setStatus( true );
enableSettings();
});
$('#save').on('click', function(){
$settings.setStatus( false );
closeSettings();
});
});
// file 1
enableSettings = function() {
if( $settings.getStatus() === true ){
//toggle emptyLink
$('.myButton').on('click', function(){
alert($settings.getStatus());
});
}
}
So as startup while clicking on "myButton" nothing happens.
After Clicking on "openSettings" and then on "myButton" i get the alert "true";
After clicking on "save" and then on "myButton" again, i get the alert "false", but it does not even trigger, because i checked it befere.... can somebody help me please?
Where is my mistake?
I think you probably want to put the check for status inside the .myButton click handler instead of outside. That way you only need to apply the handler once and it will either work or not depending on the value of status.
$(document).ready(function() {
var $settings = new settings( false ); // keep out of global scope
$( '#openSettings' ).on('click', function() {
$settings.setStatus( true );
});
$('#save').on('click', function(){
$settings.setStatus( false );
});
$('.myButton').on('click', function(){
if ($settings.getStatus()) {
alert($settings.getStatus());
}
});
});
First of all, you can write JavaScript with less code than e.g. Java. You don't need the getter and setter methods since there is no package visibility. Since you do nothing with the setters you can access your fields directly. This is less code to read and less code where you can have errors. So get rid of useless code (remember this is not the request do code one-liners). Search the internet for "clean code".
Since you are in JavaScript you can do better than that. A smaller approach to store your information.
var mySetting = {};
mySetting.status = true
console.log( mySetting.status );
mySetting.status = false;
console.log( mySetting.status );
Remember to keep your global space clean! Search the internet for "javascript global scope pollution". So do this within your scope.
Your main problem is, that you are using closures. You probably don't want to use it in your case. Search the internet for "javascript closure tutorial". There are a lot of good ones out there.
Since you are using the Jquery, you can use the .data() function to store your information.
See http://api.jquery.com/jquery.data/
$(function(){
$( '#openSettings' ).on('click', function() {
$('#settings').data( "status", true );
enableSettings();
});
$('#save').on('click', function(){
$('#settings').data( "status", false );
closeSettings();
});
$('.myButton').on('click', function(){
alert($('#settings').data());
});
});
Or within the HTML itself. See http://api.jquery.com/attr/
$('#settings').attr( "status", true );
console.log( $('#settings').attr( "status" ) );
Or as switches.
$('#settings').addClass( "settingsEnabled" );
$('#settings').removeClass( "settingsEnabled" );
console.log($('#settings').hasClass('settingsEnabled'));
Use .data() if you want to store object references and HTML for simple information like switches etc. The benefit is, that you can reach that information even with CSS.
And please get rid of the $ prefix in your own code since it has no meaning. If you use frameworks like angular it will help you to identify the origin or like the $$ the ("don't") use of it.
So I have this gridview:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'symptoms-grid',
'selectableRows'=>1, //ability to select one symptom at a time
'dataProvider'=>$model->search(),
'htmlOptions'=>array('id'=>'symptomsSearchgrid'),
'columns'=>array(
'symptomCode',
'title',
'inclusions',
'exclusions',
'symptomCategory',
),
)); ?>
And this javascript....script:
Yii::app()->clientScript->registerScript('search', "
$( document ).ready(function() {
$('#symptomSelectDiv').hide();
$('#categorySelectDropDown').change(function(){
$('#symptomSelectDiv').show();
$('#symptoms-grid').yiiGridView('update', {
data: $(this).serialize()
});
return false;
});
$('#symptomsSearchgrid table tbody tr').on('click', function() {
var firstColVal = $(this).find('td:first-child').html();
$('#symptomToBeSearched').val(firstColVal);
});
});
");
My problem is that I can only either get the
$('#symptoms-grid').yiiGridView('update', {
data: $(this).serialize()
});
function to work or the:
$('#symptomsSearchgrid table tbody tr').on('click', function() {
var firstColVal = $(this).find('td:first-child').html();
$('#symptomToBeSearched').val(firstColVal);
});
one, and it seems quite random too. Basically in order to get the other function to "start working" I have to change the id (either the grid id or the DOM id) of one function to something different for the other function to work (while the other doesn't).
So let's say at first the update function works and the click function doesn't. Then I change the ID of update to something wrong and click works. Then I change the id of update back to the correct one, but it still doesn't work, yet click works. THen I change click to a wrong id and update starts working correctly. But again, if I change click to the correct id it doesn't work.....
Any ideas what I'm doing wrong?
I think your issue is that your are giving your grid two id's one when creating it and one in htmloption.
I'm pretty new to jquery, this is what i need help with: Using jquery to see if a selector pulled any divs, find a div thats specific to example page. See if first condition is false and if so redirect to example page. Thanks for any help!
Jquery partial code: "
$('.assessment-start').click(function () {
$('#startAssessmentDialog').empty();
//block
$('#startAssessmentDialog').block(_blockUISettings);
//block
var link = $('#startAssessmentDialog').attr('link');
AjaxUtil.Services.PageProxy.SendData(link, GLOBAL._HTTPVerbs.GET, {},
function (data) {
var $data = $(data);
$('#startAssessmentDialog').html($data.find('#surveyContainer'));
$('div[name*="*"]').val('*');</script>
// hide the unmapped capability areas
$("#unmappedCapabilityAreas").hide();
// unblocking
$('#startAssessmentDialog').unblock();
// unblocking
},
function (exception) {
AjaxUtil.DefaultExceptionHandler(exception);
$('#startAssessmentDialog').unblock();
}
);
"
Html code:
<div link="/Survey/details/#Global.CGSs[Model.CGSVersionID.Value].SelfAssessmentSurveyResourceID/#Model.ResourceID" id="startAssessmentDialog" class="noDisplay">
</div>
Seeing if selector got any divs:
var selector_pulled_divs=($(selector).filter("div").length!=0)
We'd need some code to work with to help you further.
You can check with nodeName property:
if ($(".selector").get(0).nodeName == 'div') { \\do stuff }
I think you're trying to do something:
if( $('#selector').length ) {
// do something if selector pulled a div
} else {
// do something if selector not pulled a div
// for page redirect write following line
window.location = 'YOUR_URL';
}
$('#selector').length will check the exists of div with id=selector.