I am currently in the process of working on the app which is through modular pattern.
The problem i am currently getting is that once the Ajax is complete, i want to be able to fire a function within the object. The object i can see but when i specify a function, it fails and comes back as Undefined.
JS
var TestCase = {
settings: {
cu: $('.select'),
},
init: function() {
se = this.settings;
},
windowsReady: function() {
TestCase.init();
if ($.fn.selectBox) {
TestCase.selectBind();
}
},
ajaxComp: function() {
TestCase.init();
TestCase.selectBind();
},
selectBind: function(){
se.cu.selectBox();
},
};
JS Fire - The selectBind works fine when its loaded through the ready call. However as mentioned before, the ajaxcomplete keeps coming back as Undefined for TestCase.ajaxComp(); or a direct call for TestCase.selectBind(); Please note that when i console.log(TestCase) it lists all the objects.
$(document).ready(function () {
TestCase.windowsReady();
});
$(document).ajaxSuccess(function() {
console.log(TestCase);
TestCase.ajaxComp();
console.log('completed');
});
This is happenning because of this line:
se = this.settings;
The this in the scope of your $(document).ajaxSuccess(...) method will be the jQuery object, not TestCase object.
Try changing it to se = TestCase.settings;
Related
In my javascript file, I have defined an app object that takes an initialization function which is triggered upon document ready via JQuery.
$(document).ready(function() {
console.log("JQuery ready");
app.initialize();
});
The app is defined as
var app = {
_GPS_ENABLED: false,
initialize: function() {
var self = this;
// deviceready Event Handler
$(document).on('deviceready', function() {
... ...
// BIND A CLICK EVENT TO A FUNCTION DEFINED IN A LATER STEP
$('#isGPSenabled').on("click", self.isGPSenabled);
... ...
});
},
isGPSenabled: function() {
cordova.plugins.diagnostic.isGpsLocationEnabled(function(enabled) {
// HERE I NEED TO ACCESS THE "APP" ATTRIBUTE "_GPS_ENABLED"
._GPS_ENABLED = enabled; // HOW CAN I ACCESS THE _GPS_ENABLED ATTRIBUTE ON APP
});
}
}
The HTML part has:
<button id = "isGPSenabled">IS GPS ENABLED</button>
How can I access the app's attribute from the function attached to a button?
Previously I've referenced the object by it's name within itself. I think it was a pattern I saw once which worked for my needs at the time. Haven't really thought about the positives or negatives much but it has never caused me any issues in previous work.
Here is an example to to demonstrate:
const app = {
isEnabled: null,
init: () => {
app.isEnabled = false;
},
toggleEnabled: () => {
app.isEnabled = !app.isEnabled;
},
displayEnabled: () => {
console.log('isEnabled?:', app.isEnabled);
}
}
app.displayEnabled(); // null
app.init();
app.displayEnabled(); // false
app.toggleEnabled();
app.displayEnabled(); // true
You can add JS events in SugarCRM 7.2 by creating a custom record.js.
The problem I'm having is that they fire before the page is loaded so elements I'm trying to affect don't exist.
I have tried the following:
$(document).ready(function() { alert(0); }) // fires before page is loaded
$(document).on('load', function() { alert(1); }) // doesn't fire at all
$(window).load(function() { alert(2); }) // doesn't fire at all
Any help in resolving this would be much appreciated.
record.js
({
extendsFrom: 'RecordView',
initialize: function (options) {
this._super('initialize', [options]);
SUGAR.util.ajaxCallInProgress = function () {
alert(0);
$('[name="duplicate_button"]').hide();
},
})
The way I got this to work was to use the following code in custom/modules//clients/base/views/record/record.js
({
extendsFrom: 'AccountsRecordView',
initialize: function (options) {
this._super('initialize', [options]);
this.on("render", this.SetHomeButtons, this); //calls SetHomeButtons
},
SetHomeButtons: function () {
some code ....
},
})
The function SetHomeButtons is called once the page is loaded
Another way of doing it is to overwrite the render function to call your custom code
That doesn't work because of AJAX.
Edit: in Sugar 7 you have the function SUGAR.util.ajaxCallInProgress() it retruns false when every Request is done (all Content Elements have been loaded)
I'm using selecter jquery. I initialize it by typing the code
$("select").selecter();
I need to make sure that the formstone selecter jquery library has completed before i start appending elements. So what i did is to is use the $.when function
initialize: function(){
$.when($("select").selecter()).then(this.initOptions());
},
initOptions: function(){
this.$el.find('.selecter').addClass('something');
}
But this does not work. How can i wait while formstone selecter is doing its thing before i execute another function?
Thanks,
UPDATE
Here's the update of what i did but it does not work.
initialize: function(){
$("select").selecter({callback: this.initOptions });
},
initOptions: function(){
this.$el.find('.selecter').addClass('something');
}
There is a callback option.
The function passed as a callback will receive the newly selected value as the first parameter
Should be $("select").selecter(callback: function() { alert('callback fired.') });
or as shown
$("select").selecter({
callback: selectCallback
});
function selectCallback(value, index) {
alert("VALUE: " + value + ", INDEX: " + index);
}
The problem which I think regarding the callback edited code is that this can refer to anything. Try the following code
var selectorObj = {
initialize: function(){
$("select").selecter({callback: selectorObj.initOptions });
},
initOptions: function(){
this.$el.find('.selecter').addClass('something');
}
};
Created a working fiddler for you http://jsfiddle.net/6Bj6j/
The css is out of shape. Just select what is poping up when you click on the dropdown. You will get an alert which is written in the callback.
The problem with the provided snippet is the scope of the callback:
var selectorObj = {
initialize: function(){
$("select").selecter({ callback: selectorObj.initOptions });
},
initOptions: function(){
// 'this' refers to the "$('.selecter')" jQuery element
this.addClass('something');
}
};
However if you just need to add a class to the rendered element, you should use the 'customClass' option:
$("select").selecter({
customClass: "something"
});
If you need to do more, you can always access the Selecter element directly:
var $selecter = $("select").selecter().next(".selecter");
$selecter.addClass("something").find(".selecter-selected").trigger("click");
Sidenote: I'm the main developer of Formstone. If you have any suggestions for new features or better implementation, just open a new issue on GitHub.
i have some links in a web page ,what i want to do :
Trigger click event on every link
When the page of every link is loaded , do something with page's DOM(fillProducts here)
What i have tried :
function start(){
$('.category a').each(function(i){
$.when($(this).trigger('click')).done(function() {
fillProducts() ;
});
})
}
Thanks
What you want to do is much more complicated than you seem to be giving it credit for. If you could scrape webpages, including AJAX content, in 7 lines of js in the console of a web browser you'd put Google out of business.
I'm guessing at what you want a bit, but I think you want to look at using a headless browser, e.g. PhantomJs. You'll then be able to scrape the target pages and write the results to a JSON file (other formats exist) and use that to fillProducts - whatever that does.
Also, are you stealing data from someone else's website? Cause that isn't cool.
Here's a solution that may work for you if they are sending their ajax requests using jQuery. If they aren't you're going to need to get devilishly hacky to accomplish what you're asking (eg overriding the XMLHttpRequest object and creating a global observer queue for ajax requests). As you haven't specified how they're sending the ajax request I hope this approach works for you.
$.ajaxSetup({
complete: function(jQXHR) {
if(interested)
//do your work
}
});
The code below will click a link, wait for the ajax request to be sent and be completed, run you fillProducts function and then click the next link. Adapting it to run all the clicks wouldn't be difficult
function start(){
var links = $('.category a');
var i = 0;
var done = function() {
$.ajaxSetup({
complete: $.noop//remove your handler
});
}
var clickNext = function() {
$(links.get(i++)).click();//click current link then increment i
}
$.ajaxSetup({
complete: function(jQXHR) {
if(i < links.length) {
fillProducts();
clickNext();
} else {
done();
}
}
});
clickNext();
}
If this doesn't work for you try hooking into the other jqXHR events before hacking up the site too much.
Edit here's a more reliable method in case they override the complete setting
(function() {
var $ajax = $.ajax;
var $observer = $({});
//observer pattern from addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjquery
var obs = window.ajaxObserver = {
subscribe: function() {
$observer.on.apply($observer, arguments);
},
unsubscribe: function() {
$observer.off.apply($observer, arguments);
},
once: function() {
$observer.one.apply($observer, arguments);
},
publish: function() {
$observer.trigger.apply($observer, arguments);
}
};
$.ajax = function() {
var $promise = $ajax.apply(null, arguments);
obs.publish("start", $promise);
return $promise;
};
})();
Now you can hook into $.ajax calls via
ajaxObserver.on("start", function($xhr) {//whenever a $.ajax call is started
$xhr.done(function(data) {
//do stuff
})
});
So you can adapt the other snippet like
function start(){
var links = $('.category a');
var i = 0;
var clickNextLink = function() {
ajaxObserver.one("start", function($xhr) {
$xhr.done(function(data) {
if(i < links.length) {
fillProducts();
clickNextLink();
} else {
done();
}
});
})
$(links.get(i++)).click();//click current link then increment i
}
clickNextLink();
}
try this:
function start(){
$('.category a').each(function(i){
$(this).click();
fillProducts() ;
})
}
I get ya now. This is like say:
when facebook loads, I want to remove the adverts by targeting specific class, and then alter the view that i actually see.
https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/
Is a plugin for firefox, this will allow you to create a javascript file, will then allow you to target a specific element or elements within the html rendered content.
IN order to catch the ajax request traffic, you just need to catcher that within your console.
I can not give you a tutorial on greasemonkey, but you can get the greasemonkey script for facebook, and use that as a guide.
http://mashable.com/2008/12/25/facebook-greasemonkey-scripts/
hope this is it
I'm using require.js with backbone.js to structure my app. In one of my views:
define(['backbone', 'models/message', 'text!templates/message-send.html'], function (Backbone, Message, messageSendTemplate) {
var MessageSendView = Backbone.View.extend({
el: $('#send-message'),
template: _.template(messageSendTemplate),
events: {
"click #send": "sendMessage",
"keypress #field": "sendMessageOnEnter",
},
initialize: function () {
_.bindAll(this,'render', 'sendMessage', 'sendMessageOnEnter');
this.render();
},
render: function () {
this.$el.html(this.template);
this.delegateEvents();
return this;
},
sendMessage: function () {
var Message = Message.extend({
noIoBind: true
});
var attrs = {
message: this.$('#field').val(),
username: this.$('#username').text()
};
var message = new Message(attrs);
message.save();
/*
socket.emit('message:create', {
message: this.$('#field').val(),
username: this.$('#username').text()
});
*/
this.$('#field').val("");
},
sendMessageOnEnter: function (e) {
if (e.keyCode == 13) {
this.sendMessage();
}
}
});
return MessageSendView;
});
When keypress event is triggered by jquery and sendMessage function is called - for some reason Message model is undefined, although when this view is first loaded by require.js it is available. Any hints?
Thanks
Please see my inline comments:
sendMessage: function () {
// first you declare a Message object, default to undefined
// then you refrence to a Message variable from the function scope, which will in turn reference to your Message variable defined in step 1
// then you call extend method of this referenced Message variable which is currently undefined, so you see the point
var Message = Message.extend({
noIoBind: true
});
// to correct, you can rename Message to other name, e.g.
var MessageNoIOBind = Message.extend ...
...
},
My guess is that you've bound sendMessageOnEnter as a keypress event handler somewhere else in your code. By doing this, you will change the context of this upon the bound event handler's function being called. Basically, when you call this.sendMessage(), this is no longer your MessageSendView object, it's more than likely the jQuery element you've bound the keypress event to. Since you're using jQuery, you could more than likely solve this by using $.proxy to bind your sendMessageOnEnter function to the correct context. Something like: (note - this was not tested at all)
var view = new MessageSendView();
$('input').keypress(function() {
$.proxy(view.sendMessageOnEnter, view);
});
I hope this helps, here is a bit more reading for you. Happy coding!
Binding Scopes in JavaScript
$.proxy