Pass the request to server sammyjs - sammy.js

New to sammyjs. We broadly have two modules, one is Server side rendered and another is a de-coupled client app. We have implemented ko and sammy and its working good. But for some requests, I need to pass it on to the server. Is that possible with sammy?
Sammy(function () {
this.get( ".*", function () {
var view = window.location.pathname;
if( view == "/" )
appViewModel.currentView( "home-page" );
else if( view == "/product" )
appViewModel.currentView( "product-page" );
else if( view == "/admin" )
return false; // SSR Page
});
}).run();

The answer turned out to be very simple, just don't capture the request in the first place.
this.get( "^(?!\/admin$).*$", function() {
// Do something
});

Related

#9073 ImageUpload callback can not be called cross-domain CKEditor

https://dev.ckeditor.com/ticket/9073
I had a unique scenario that requires my image uploader/image management system to be hosted on a separate sever. Because of this, I ran into the security-error-blocked-a-frame-with-origin-from-accessing-a-cross-origin-frame error.
Through my research I was not able to identify a clear answer to solving this problem; although there may already be a way to do this/better way, I wanted to post my workaround here in case anyone else can use it.
CKEDITOR.on( 'dialogDefinition', function( ev ) {
console.log('dialof def');
var dialogName = ev.data.name,
dialog = ev.data.definition.dialog;
//verify dialog is of name image
if ( dialogName == 'image' ) {
//on show create click event listener
dialog.on('show', function(){
window.addEventListener("click", evalClickEventType, false);
})
//evaluate click event to ensure it is Browse Server button
function evalClickEventType(event){
if(event.srcElement.innerText == 'Browse Server'){
createMessageListener();
}
//if either type of close, or ok, remove clickEventListener
else if (event.srcElement.innerText == 'OK' || event.srcElement.innerText == 'X' || event.srcElement.innerText == 'Cancel'){
window.removeEventListener("click", evalClickEventType, false);
}
}
//add event listener for type message
function createMessageListener()
{
window.addEventListener("message", receiveMessage, false);
}
//set value to txtUrl when event message is emitted.
function receiveMessage(event){
CKEDITOR.dialog.getCurrent().setValueOf( 'info', 'txtUrl', event.data );
window.removeEventListener("message", receiveMessage, false);
}
}});
then simply replace
window.opener.CKEDITOR.tools.callFunction( funcNum, fileUrl );
with this in your image management solution to pass the url from cross-origin server.
var targetWindow = window.opener;
targetWindow.postMessage(imgSrc, "*")
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

Make Pinterest Profile Widget Secure

I am using the below page to create a Pinterest Profile widget:
https://business.pinterest.com/en/widget-builder#do_embed_user
The problem is that when the widget displays the images use non secure links. I need to display the widget on a secure page so need them to be https://
Any ideas how I can go about this?
Ok so after a bit of research I have made a pretty intense hack to make this work. Pintrest does serve https content, it is just that for some reason they have not included this in their API. So I have stepped through the API and found the attribute setter that sets attributes to any elements the API creates.
Anyway.. here is the fiddle: https://jsfiddle.net/nanff007/1/ (make sure to https)
And here is the code that performs the magic...
This is a workaround/hack or whatever you want to call it. It will not work forever. It may also not work in all countries as the akamai urls may change. The best option would be to raise a request ticket with Pintrest.
(function() {
$('a[data-pin-do]').each(function () {
$(this).attr('data-pin-dont', $(this).attr('data-pin-do'));
$(this).removeAttr('data-pin-do');
});
var timer = setInterval(function () {
for (prop in window) {
if (prop.search(/^PIN_/) > -1 && typeof window[prop] != 'boolean') {
clearInterval(timer);
window[prop].f.set = function (el, att, string) {
if(att == 'src' && el.tagName.toLowerCase() == 'img') {
string = string.replace(/(^http:\/\/)/i, "https://s-");
}
if (typeof el[att] === 'string') {
el[att] = string;
} else {
el.setAttribute(att, string);
}
};
$('a[data-pin-dont]').each(function () {
$(this).attr('data-pin-do', $(this).attr('data-pin-dont'));
$(this).removeAttr('data-pin-dont');
});
window[prop].f.init();
break;
}
}
}, 100);
}());
Just Remove the https: and start with // as the beginning of the link.
For Example:
< a href="//sub-domain.example.com">Acme Widgets
Remove the spaces before > and after < in the above example

Knockout SPA Ajax loaded templates

I am lost between the possibilities offered to handle this case: let's say we have the following constraints:
Knockout
SPA with Sammy.js - Html loaded via Ajax
My page:
+-------------------------------+
| #navigation |
+---------+---------------------+
| #sidebar| #content |
| | |
| | |
| | |
+---------+---------------------+
Currently, I have one appViewModel which handle the data-bind for all the shared elements of my website: #navigation and #sidebar. This appViewModel has observable used on every pages of my website.
appViewModel = function () {
var self = this;
self.sidebarItemArray = ko.observableArray([x, y, z]);
self.currentRoute = ko.observable();
...
self.updateView = function(path, currentRoute) {
return $.get(path, function( data ) {
var $data = $(data);
// Updates #content, TITLE and update the currentRoute observable.
$( '#content' ).replaceWith($data.find('#content'));
document.title = $data.filter('title').text();
self.currentRoute(currentRoute);
}, 'html');
}
Sammy(function() {
this.get(':link'', function() {
self.updateView(this.path, this.params.link);
});
}).run();
}
ko.applyBindings(new appViewModel());
Now, let's say that #content is a piece of DOM loaded through an Ajax Call. Each time a user click a link inside #navigation or #sidebar, Sammy.js intercept it and then update #content. The problem is that the new DOM inside #content has data-bindings itself.
1) First, should I use the html data-bind on #content, replaceWith(as above) or the template binding with custom function to get the template?
(http://knockoutjs.com/documentation/template-binding.html#note-5-dynamically-choosing-which-template-is-used)? What is the best practice here?
2) Should Sammy necessary lives inside the appViewModel as in the documentation or elsewhere is just fine?
3) Once the updateView method is completed, how would you bind the new DOM? Like below? Isn't there a risk of rebinding some DOM because ko.applyBindings has already been called without second argument?
ko.applyBindings(new routeSpecificViewModel() , document.getElementById("content"));
I am thankful for your help.
One simple solution is to make the page's viewmodel an observable, and load it ondemand. Use a variable to record if ko.applyBindings has been called. Example from the knockout-spa framework:
/*! knockout-spa (https://github.com/onlyurei/knockout-spa) * Copyright 2015-2016 Cheng Fan * MIT Licensed (https://raw.githubusercontent.com/onlyurei/knockout-spa/master/LICENSE) */
define(['app/shared/root-bindings', 'framework/page-disposer', 'ko', 'sugar'], function (
RootBindings, PageDisposer, ko) {
var initialRun = true;
var Page = {
init: function (name, data, controller, path) {
Page.loading(false);
name = name.toLowerCase();
if ((Page.page().name == name) && (Page.page().data == data)) { // if the requested page is the same page, immediately call controller without going further
if (controller) {
controller(data);
}
document.title = Page.title();
if (Page.initExtra) {
Page.initExtra(name, data, controller);
}
return data;
}
var autoDispose = (Page.page().data.dispose && Page.page().data.dispose(Page)) || true; // if the requested page is not the same page, dispose current page first before swap to the new page
if (autoDispose !== false) {
// auto-dispose page's exposed observables and primitive properties to initial values. if not desired, return
// false in dispose function to suppress auto-disposal for all public properties of the page, or make the
// particular properties private
PageDisposer.dispose(Page.page().data);
}
PageDisposer.init(data); //store initial observable and primitive properties values of the page
var initialized = (data.init && data.init(Page)) || true; // init view model and call controller (optional) before template is swapped-in
if (initialized === false) {
return false; // stop initialization if page's init function return false (access control, etc.)
}
if (controller) {
controller(data);
}
Page.pageClass([name, ('ontouchstart' in document.documentElement) ? 'touch' : 'no-touch'].join(' '));
Page.page({
name: name,
data: data,
path: path
}); // to test if template finished rendering, use afterRender binding in the template binding
document.title = Page.title();
if (Page.initExtra) {
Page.initExtra(name, data, controller); // useful for common init tasks for all pages such as anaylitics page view tracking, can be set in RootBindings
}
if (initialRun) {
ko.applyBindings(Page, document.getElementsByTagName('html')[0]); // apply binding at root node to be able to bind to anywhere
initialRun = false;
}
return data;
},
page: ko.observable({
name: '', // name of the page - auto-set by the framework, no need to worry
data: {
init: function () {}, // preparation before the page's template is rendered, such as checking access control, init/instantiate modules used by the page, etc.
dispose: function () {} // properly dispose the page to prevent memory leaks and UI leftovers (important for SPA since page doesn't refresh between page views) - remove DOM element event listeners, dispose knockout manual subscriptions, etc.
}
}),
pageClass: ko.observable(''),
loading: ko.observable(false),
title: function () {
return Page.page().name.titleize(); // override in RootBindings as needed
}
};
Object.merge(Page, RootBindings); // additional root bindings as needed by the app
return Page;
});
A mini but full-fledged SPA framework built on top of Knockout, Require, Director, jQuery, Sugar.
https://github.com/onlyurei/knockout-spa
Live Demo: https://knockout-spa.mybluemix.net

JQuery ajax calls collision using Play! framework

When some action is invoked in my page, I make two ajax calls (A, B) to two different methods on my server.
Most of the times each request gets its matching response, but here and there both requests gets the same response! (of one of the requests - A,A or B,B)
The Ajax calls are made using JQuery and the server methods are implemented using Play! framework (in java).
Does anyone have any idea why does it happen and how to resolve it?
Thanks!
Ajax Call A:
var renderTypePreviewPageRoute = jsRoutes.com.eyeview.connectad.controllers.solutions.FeedLibrary.getFeedTypePreviewPage(feedHashId, feedType);
// Makes an ajax call that gets the rendered solution page
$.ajax({
// Sets the route (URL) of the server call
url:renderTypePreviewPageRoute.url,
// Sets the method (GET / POST) of the server call
type:renderTypePreviewPageRoute.method,
//data:{ hashId: feedHashId, feedType: feedType, withPreview: withPreview }-->
// In case of success
success:function(result) {
var typePreviewElement = $('#typePreviewSection');
// Set the feed preview section html content to the rendered content got from the server
typePreviewElement.html(result);
typePreviewElement.removeClass('hidden');
$('#feedPreviewGrid tr:eq(1)').removeClass('hidden');
if ($('#feedPreviewSection').is(':visible')){
typePreviewElement.show('blind');
}
var feedURL = urlEle.val();
if (waitForFileTypePreview && feedURL != "") {
feedEditNS.renderFilePreviewSection(true);
}
},
// In case of failure
error:function(xhr, ajaxOptions, thrownError) {
// Shows the error message
showError(xhr.responseText);
// Clears the preview section
feedEditNS.clearTypePreviewSection();
var feedURL = urlEle.val();
if (waitForFileTypePreview && feedURL != "") {
feedEditNS.renderFilePreviewSection(true);
}
}
Ajax Call B:
var renderFilePreviewPageRoute = jsRoutes.com.eyeview.connectad.controllers.solutions.FeedLibrary.getFeedFilePreviewPage(feedHashId);
// Makes an ajax call that gets the rendered solution page
$.ajax({
// Sets the route (URL) of the server call
url:renderFilePreviewPageRoute.url,
// Sets the method (GET / POST) of the server call
type:renderFilePreviewPageRoute.method,
// In case of success
success:function(result) {
// Set the feed preview section html content to the rendered content got from the server
$('#filePreviewSection').html(result);
// Shows the feed preview section
$('#verticalLine').show('blind');
$('#leftShadow').show('blind');
$('#rightShadow').show('blind');
$('#feedPreviewSection').show('blind');
feedEditNS.createDataTable(withHeaders);
waitForFileTypePreview = false;
},
// In case of failure
error:function(xhr, ajaxOptions, thrownError) {
// Shows the error message
showError(xhr.responseText);
// Clears the preview section
feedEditNS.clearFilePreviewSection();
waitForFileTypePreview = false;
}
I could not resolve the problem.
So, I ended up combining both calls to one call to a single server side method.
This method returned a JSON object containing both calls answers.
I ran into this exact issue (3'ish years later...) I am still not sure what the real problem is, but as a workaround I ended up using setTimeout() inside my Angular controller.
myApp.controller('myCtrl', function($scope, myRestApi) {
$scope.restCallOne = function() {
myRestApi.callOne().then(
// handle result one
);
};
$scope.restCallTwo = function() {
myRestApi.callTwo().then(
// handle result two
);
};
// loads each time the view is shown
// *** race condition when calling consecutively without a delay ***
//$scope.restCallOne();
setTimeout($scope.restCallOne, 100);
$scope.restCallTwo();
});

Two ajax function calls on single click

I've some folders in a div and contents of those folders are shown in tree view(when small plus button is clicked) using following code:
echo '<span class="toggle" onclick="getchildren(\''.$objectnode["fid"].'\', \'childdiv'.$objectnode["fid"].'\');" ></span>';
when folder is clicked,its contents are shown in another div,parallel to it using following code:
<span><?php echo $objectnode["object_name"]; ?></span>
Now what i want to do is, when i click on folder name,its contents should be load in div parallel to it as well as its child nodes should also be visible or expand at the same time. Any help will be appreciated
Just make two ajax calls. Ajax calls are asynchronous and you can make as many as you like. For example, you could do something like this:
function ajax(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', 'yourpage.php', true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
// Your callback code goes here
xmlhttp.responseXML; // this is the response data
}
};
xmlhttp.send(yourdatahere);
var xmlhttp2 = new XMLHttpRequest();
xmlhttp2.open('POST', 'yourpage.php', true);
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4) {
// Your callback code goes here
xmlhttp2.responseXML; // this is the response data
}
};
xmlhttp2.send(yourdatahere);
}
Call this function from your onclick function and that should do the trick. You can also nest the function calls. For example, if you're waiting on data from the first call, put the second ajax call in the callback from the first and do all of the updating. You won't need to wait for the second ajax call to return to update the DOM.
You could also make a separate ajax call for each child node, and if you want to do that for all of the child nodes, you'll have to do some recursion, such as:
function ajax(parentNode){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', 'yourpage.php', true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
// Your callback code goes here
xmlhttp.responseXML; // this is the response data
// do stuff with responseXML
}
};
xmlhttp.send(yourdatahere);
var i;
for(i = 0; i < parentNode.childNodes.length; i++){
ajax(parentNode.childNodes[i]);
};
}
There are already plugins made for this. I know jQuery has one for it's framework. I built my own because it wasn't exactly what I wanted. I hope this helps!

Resources