I use the FB Javascript API to create Like-buttons. The button appears in the lightbox-view of an image based on lightbox2 (http://lokeshdhakar.com/projects/lightbox2/)
I create once a div with an id
.append($('<div/>', {
"id": 'fb-image-like', "data-send" : 'false', "data-layout" : 'button_count', "data-width" : '250', "data-show-faces" : 'true', "data-colorscheme" : 'dark', "data-font":'arial'
}))
on lightbox's "build"-event. On "updateDetails" (Show next image) I set the data-href-attribute, append the "fb-like"-class and start window.fbAsyncInit();
$('.fb-like').removeClass("fb-like");
//FB._initialized = false;
$("#fb-image-like").attr("data-href", url).addClass("fb-like");
window.fbAsyncInit();
Facebook creates the iframe with Like-button and everything works perfectly. On next image the generated code looks good (replaced data-href) but the Like-Button appears as already liked, because the URL in like.php doesn't change. The window.fbAsyncInit(); doesn't re-init the session. If I dislike now, the last image will be disliked. What can I do, to re-init the Facebook-session completely?
The window.fbAsyncInit(); doesn't re-init the session.
Of course it does not, because that’s not it’s purpose at all.
Just call FB.XFBML.parse again (probably with a scope parameter), to have it re-parse your like button tag.
Related
I am new to developing application using oracle apex. Please excuse me if this question seems very trivial in nature.
In a nutshell, I am trying to invoke a REST service programmatically to populate an interactive grid on oracle apex page. Here's what I already tried.
Created a page that has a button to invoke a process.
The process invokes a REST service to get all order lines belonging to a particular order. The sample response from the REST service is as below
{
"items": [{
"HeaderId": 300100550016803,
"FulfillLineId": 300100550016806,
"SourceTransactionLineId": "1",
"SourceTransactionLineNumber": "1",
"OrderedQuantity": "10",
"OrderedUOM": "Each",
"RequestedFulfillmentOrg": "Vision Corporation"
},{
"HeaderId": 300100550016803,
"FulfillLineId": 300100550016807,
"SourceTransactionLineId": "2",
"SourceTransactionLineNumber": "2",
"OrderedQuantity": "15",
"OrderedUOM": "Each",
"RequestedFulfillmentOrg": "Seattle Manufacturing"
}]
}
If the rest service invocation was successful (http status code: 200), then I create the apex_collection as below in the same process. Also, I have set one of the page fields (P3_REFRESH_ORDER_LINES_GRID) to ‘Y'. On page load, the value for this attribute must be null.
if apex_web_service.g_status_code = 200 then --OK
dbms_output.put_line( 'Response : ' || l_data ); --if response was OK, print it
apex_collection.create_or_truncate_collection( 'OrderLines' );
apex_collection.add_member(
p_collection_name => 'OrderLines',
p_clob001 => l_data );
:P3_REFRESH_ORDER_LINES_GRID := 'Y';
end if;
I have then used the below SQL query to populate data into the interactive grid
Set the region type to “Interactive Grid”
Source: Local Database
Type: SQL query
SELECT ol.fulfill_line_id as FulfillLineId, ol.quantity as Quantity
FROM APEX_collections c,
JSON_TABLE(
c.clob001, -- the following lines depend on your JSON structure
'$.items[*]'
columns(
fulfill_line_id number path '$.FulfillLineId',
quantity number path '$.OrderedQuantity')
) ol
WHERE c.collection_name = 'OrderLines';
Then, I have setup a dynamic action on the page item (Its a hidden text field)
- P3_REFRESH_ORDER_LINES_GRID
- Dynamic Action name : RefreshGrid
- When: Event Name: Change
- selection type: Item
- Item - P3_REFRESH_ORDER_LINES_GRID
- Client side condition - Type: Item is not null
- Item - P3_REFRESH_ORDER_LINES_GRID
- True condition: Action: Refresh, selection type: Region, Region: Order Lines (Name of the region containing the IG)
After I click on the button to invoke the rest service to fetch the order lines, the interactive grid does not display any data. Can you suggest where am I going wrong here?
Potential Issue(s)
Step 1 You didn't really specify how your button works. If it is submitting the page, you may have problems with P3_REFRESH_ORDER_LINES_GRID field remaining null.
You could have Server-Side conditions preventing the invocation or on Page-Load you may be resetting P3_REFRESH_ORDER_LINES_GRID to null, and Step 5 will NOT trigger.
Step 3(Most Likely Issue) If you are not submitting the page, and you just have a Dynamic Action, executing Server-Side code: you may have forgotten to include P3_REFRESH_ORDER_LINES_GRID in the Items to Return.
Your P3_REFRESH_ORDER_LINES_GRID flag will remain null and Step 5 will NOT trigger.
To Debug
You can try debugging your page here by checking Session under Developer Tools. I would make sure each step work and executes however I intend it to execute.
Also leverage APEX_DEBUG in my PL/SQL
Open your Browser's Developer Tools and look under Console. You should see Dynamic Action Fired lines there if Step 5 is being triggered at all!
As you have not shared how your debugging went, and other observations after clicking the button, such as:
Was the collection created?
Is there data in the collection?
What's the value of P3_REFRESH_ORDER_LINES_GRID
You should be able to see what the answers are for the above using Session.
This is a follow on to "APEX row selector" posted 5 days ago.
The problem was collecting multiple values from an interactive grid. From the excellent links to post supplied I was able to achieve this. However, the next part of the project is to open an edit dialog page and update multiple values.
I added this code to the attribute of the interactive grid:
function (config)
{
var $ = apex.jQuery,
toolbarData = $.apex.interactiveGrid.copyDefaultToolbar(),
toolbarGroup = toolbarData.toolbarFind("actions3");
toolbarGroup.controls.push(
{
type: "BUTTON",
action: "updateCar",
label: "Edit Selected Cars",
hot: true,
});
config.toolbarData = toolbarData;
config.initActions = function (actions)
{
// Defining the action for activate button
actions.add(
{
name: "updateCar",
label: "Edit Selected Cars",
action: updateCar
});
}
function updateCar(event, focusElement)
{
var i, records, model, record,
view = apex.region("ig_car").widget().interactiveGrid("getCurrentView");
var vid = "";
model = view.model;
records = view.getSelectedRecords();
if (records.length > 0)
{
for (i = 0; i < records.length; i++)
{
record = records[i];
alert("Under Development " + record[1]);
vid = vid + record[1] + "||";
apex.item("P18_CAR").setValue(vid);
// need to open next page here and pass parameters
}
}
}
return config;
}
I need to know how to open a form and have the parameter values available to pass to an oracle update script.
Thank you for any help you can provide. I did find some posts but I really need a good example. I have tried everything to no avail.
There are various ways you could do this. Here's one way, perhaps someone else will offer a more efficient option.
The JavaScript options for navigation in APEX are documented here:
https://docs.oracle.com/en/database/oracle/application-express/19.1/aexjs/apex.navigation.html
Since you're trying to open a separate page, you probably want to use apex.navigation.dialog, which is what APEX automatically uses when opening modal pages from reports, buttons, etc.
However, as noted in the doc, the URL for the navigation must be generated server-side for security purposes. You need a dynamic URL (one not known when the page renders), so you'll need a workaround to generate it. Once you have the URL, navigating to it is easy. So how do you get the URL? Ajax.
Create an Ajax process to generate the URL
Under the processing tab of the report/grid page, right-click Ajax Callback and select Create Process.
Set Name to GET_FORM_URL.
Set PL/SQL code to the following
code:
declare
l_url varchar2(512);
begin
l_url := apex_page.get_url(
p_application => :APP_ID,
p_page => 3,
p_items => 'P3_ITEM_NAME',
p_values => apex_application.g_x01
);
apex_json.open_object();
apex_json.write('url', l_url);
apex_json.close_object();
end;
Note that I'm using apex_item.get_url to get the URL, this is an alternative to apex_util.prepare_url. I'm also using apex_json to emit JSON for the response to the client.
Also, the reference to apex_application.g_x01 is important, as this will contain the selected values from the calling page. You'll see how this was set in the next step.
Open the URL with JavaScript
Enter the following code in the Function and Global Variable Declaration attribute of the calling page:
function openFormPage(ids) {
apex.server.process(
'GET_FORM_URL',
{
x01: ids.join(':')
},
{
success: function (data) {
var funcBody = data.url.replace(/^"javascript:/, '').replace(/\"$/,'');
new Function(funcBody).call(window);
},
error: function (jqXHR, textStatus, errorThrown) {
console.error(errorThrown);
// handle error
}
}
);
}
In this case, I'm using apex.server.process to call the server-side PL/SQL process. Note that I'm passing the value of ids.join(':') to x01. That value will become accessible in the PL/SQL code as apex_application.g_x01. You can use additional items, or you can pass a colon-delimited string of values to just one item (as I'm doing).
The URL that's returned to the client will not be a standard URL, it will be a JavaScript snippet that includes the URL. You'll need to remove the leading and trailing parts and use what's left to generate a dynamic function in JavaScript.
This is generally frowned upon, but I believe it's safe enough in this context since I know I can trust that the response from the process call is not malicious JavaScript code.
Add a security check!!!
Because you're creating a dynamic way to generate URLs to open page 3 (or whatever page you're targeting), you need to ensure that the modal page is protected. On that page, create a Before Header process that validates the value of P3_ITEM_NAME. If the user isn't supposed to be able to access those values, then throw an exception.
One of the recurring problems i've been having with ionic 2 is it's storage service. I have successfully set and retrieved stored data. However, when i store something, it is inaccessible on other pages unless i refresh the page/application.
Example one: Editing a contact
I push to an edit contact page, make changes, then saveEdits. saveEdits successfully makes the change to the right contact but fails to update the contact list UNTIL the application is refreshed.
HTML:
<button (click)="saveEdits(newName, newPostCode)"ion-button round>Save Edits</button>
TypeScript:
saveEdits(newName, newPostCode){
console.log("saveid"+this.id);
this.name = newName; //saves property
this.postcode = newPostCode; //saves property
this.items[this.id] = {"id": this.id, "Name": newName, "PostCode": newPostCode};
this.storage.set('myStore',this.items);
//this.navCtrl.pop(ContactPage);
}
Example two: Accessing contacts on another page
On another page i iterate through contacts and display them in a radio alert box list. Again, the contacts are displayed successfully, but when I add a contact on the add contact page, the new contact does not appear on the radio alert box list.
addDests(){
console.log('adddests');
{
let alert = this.alertCtrl.create();
alert.setTitle('Choose Friend');
for(let i = 0; i<this.items.length; i++){
console.log('hello');
alert.addInput({
type: 'radio',
label: this.items[i].Name,
value: this.items[i].PostCode,
checked: false
});
}
alert.addButton('Cancel');
alert.addButton({
text: 'OK',
handler: data => {
console.log(data);
}
});
alert.present();
}
}
You're changing the reference the variable is pointing to:
this.items[this.id] = {"id": this.id, "Name": newName, "PostCode": newPostCode};
I assume that your LIST is iterating (ngFor) over the array referenced by this.items? If yes, update directly the properties of this.items[this.id] instead of re-initializing it.
this.items[this.id].Name = newName;
this.items[this.id].PostCode = newPostCode;
(By the way, I'd recommend to be consistent with your property naming: either Id and Name, or id and name (capital letters matter!)).
Your "list" view will always be refreshed if the references to the objects being used are not changed. The only exception would be an update made in a callback given to a third-part library. In that case, you can use NgZone to "force" Angular to take the update into account.
Also, have a look at Alexander's great advice about Observable.
You should use Angular provider(s) with Observable property to notify subscribers (other pages & components) about changes.
For example read this article: http://blog.angular-university.io/how-to-build-angular2-apps-using-rxjs-observable-data-services-pitfalls-to-avoid/
There are a lot of information on this: https://www.google.com/search?q=angular+provider+observable
I want to be able to retrieve a certain conversation when its id is entered in the URL. If the conversation does not exist, I want to display an alert message with a record not found.
here is my model hook :
model: function(params){
return this.store.filter('conversation', { status : params.status}, function(rec){
if(params.status == 'all'){
return ((rec.get('status') === 'opened' || rec.get('status') === 'closed'));
}
else{
return (rec.get('status') === params.status); <--- Problem is here
}
});
}
For example, if I want to access a certain conversation directly, I could do :
dev.rails.local:3000/conversations/email.l#email.com#/convid
The problem is when I enter a conversation id which doesn't exist (like asdfasdf), ember makes call to an inexisting backend route.
It makes a call to GET conversation/asdfasdf. I'm about sure that it is only due to the record not existing. I have nested resources in my router so I'm also about sure that it tries to retrieve the conversation with a non existing id.
Basically, I want to verify the existence of the conversation before returning something from my hook. Keep in mind that my model hook is pretty much set and won't change, except for adding a validation on the existence of the conversation with the id in the url. The reason behind this is that the project is almost complete and everything is based on this hook.
Here is my router (some people are going to tell me you can't use nested resources, but I'm doing it and it is gonna stay like that so I have to work with it because I'm working on a project and I have to integrate ember in this section only and I have to use this setup) :
App.Router.map(function(){
// Routing list to raw namespace path
this.resource('conversations', { path : '/' }, function() {
this.resource('conversation', { path : '/:conversation_id'});
});
});
This also happens when I dont specify any id and I use the hashtag in my url like this :
dev.rails.local:3000/conversations/email.l#email.com#/ would make a call to conversation/
I know it is because of my nested resource. How can I do it?
By passing a query to filter (your { status : params.status}) you are asking Ember Data to do a server query. Try removing it.
From the docs at http://emberjs.com/api/data/classes/DS.Store.html#method_filter:
Optionally you can pass a query, which is the equivalent of calling find with that same query, to fetch additional records from the server. The results returned by the server could then appear in the filter if they match the filter function.
So, remove the query:
model: function(params){
return this.store.filter('conversation', function(rec) {
if (params.status == 'all') {
return rec.get('status') === 'opened' || rec.get('status') === 'closed';
} else {
return rec.get('status') === params.status;
}
});
}
Ok so here is what I did. I removed my nested resource because I realised I wasn't using it for any good reason other than redirecting my url. I decided to manually redirect my url using javascript window.location.
This removed the unwanted call (which was caused by the nested resource).
Thanks to torazaburo, you opened my eyes on many things.
I debug my API using Xdebug and PHPStorm's debugging features. For this to work, the client needs a cookie named XDEBUG_SESSION.
When using Postman, I used to use a Chrome extension to add this cookie, and Postman's cookie interception feature to get this to work in Postman (since it's a sandboxed app).
However, I cannot create cookies in Paw. So, as a workaround, I modified the API response cookie to have the key as XDEBUG_SESSION and value as PHPSTORM, and debugging worked fine. However, this is not ideal as I would also like to set the expiry date to something far in the future (which I can't in Paw).
So, my questions are:
Is there a way to add custom cookies in Paw?
If not, is there a way to to edit the expiry date for an existing cookie (considering that name, value, domain and path are editable)?
Are there any other alternatives to achieve my objective?
I just managed to achieve this exact thing to debug my APIs with Paw (2.1.1).
You just have to Add a Header with the name Cookie and a value of Cookies picked from the dropdown that will appear. You then have to insert a Cookie named XDEBUG_SESSION with a value of PHPSTORM inside the Cookies value of the header just created.
To be more clear, you can see it in the screenshot below:
I messed around with it to see if I could create an extension. I wasn't able to, and the below does not work but thought I'd share in case anyone knows the missing pieces.
First off, there is no extension category (generator, dynamic value, importer) that this functionality falls into. I tried to make use of the dynamic value category but was unsuccessful:
CookieInjector = function(key, value) {
this.key = "XDEBUG_SESSION";
this.value = "PHPSTORM";
this.evaluate = function () {
var f = function (x,y) {
document.cookie=this.key+"="+this.value;
return true;
}
return f(this.key, this.value);
}
// Title function: takes no params, should return the string to display as
// the Dynamic Value title
this.title = function() {
return "Cookie"
}
// Text function: takes no params, should return the string to display as
// the Dynamic Value text
this.text = function() {
return this.key+"="+this.value;
}
}
// Extension Identifier (as a reverse domain name)
CookieInjector.identifier = "com.luckymarmot.PawExtensions.CookieInjector";
// Extension Name
CookieInjector.title = "Inject Cookie Into Cookie Jar";
// Dynamic Value Inputs
CookieInjector.inputs = [
DynamicValueInput("key", "Key", "String"),
DynamicValueInput("value", "Value", "String")
]
// Register this new Extension
registerDynamicValueClass(CookieInjector);
The main thing stopping this from working is I'm not sure how the request is built in PAW and not sure how to attach the cookie. I've looked through the documentation here: https://luckymarmot.com/paw/doc/Extensions/Reference/Reference, and can't find what I need.