I have single page app made with ember.js and I have some problems with implementing social sharing.
I need to implement into hbs template something like this:
Link
However when this is rendered into browser there are additional script tags concatenated within the href string, eventually the link works and I am redirected but instead title I get something like this:
<script id='metamorph-190-start' type='text/x-placeholder'></script>
MyTitle
<script id='metamorph-19...
Where I need just MyTitle.
More specifically I use the following hbs template for facebook sharing, the model is initialized into the router:
<a href="https://www.facebook.com/login.php?next=http%3A%2F%2Fwww.facebook.com%2Fsharer%2Fsharer.php%3Fs%3D100%26p%255Btitle%255D%3D{{model.title}}%26p%255Burl%255D%3D{{model.url}}%26p%255Bsummary%255D%3D{{model.summary}}%26p%255Bimages%255D%255B0%255D%3D%2540Model.EventImage%2527%253EShare&display=popup"
target="_blank">
<img src="http://www.simplesharebuttons.com/images/somacro/facebook_img.png" alt="Facebook" />
</a>
I also tried third party libraries, like janrain, ShareThis or AddThis, but with them I had initialization problems, buttons were not shown at all when placed into template, and also had problems with messages customization from the model.
Thanks,
Igor
Approach 1 - Using unbound
To get rid of the metamorph tags surrounding your model value, try using the unbound option which does exactly that:
Link
Approach 2 - Computing the URL
In the case you need the model property to be bound and reevaluating when the model changes, then a different approach might be better like for example generating the URL in the controller backing up your template.
Assuming your controller is e.g. ApplicationController and the links live in the correspondent application template then you could do the following:
App.ApplicationController = Ember.ObjectController.extend({
url: function() {
var url = this.get('model.url');
var title = this.get('model.title');
// grab here as many properties you need from your model
var href = 'http://someaddres.com?u=%#&title=%#'.fmt(url, title);
return href;
}.property('model')
});
And then use the computed url property like this in your template:
<a {{bind-attr href=url}} target="_blank">Link</a>
Hope it helps.
This actually doesn't work that well since this will open a new browser tab\window instead of the desired popup window you get when using the suggested js code form facebook # https://developers.facebook.com/docs/plugins/share-button/
Unfortunately, you also need to create an 'action' within a Ember.View (for example) that calls window.open(url,"blah","width=300,height=500")
Related
I have a template which is nested inside another template which I want to load when i click on a button.
So the nested template is loaded dynamically. This is what I have done so far.
This is the main body.html (this loads when a url is provided in the browser e.g. http://url#/newtemplate)
<div ui-view> </div>
Other section of the code has been removed for brevity
This is the new_template.html which I expects it to show when I click a button.
When I put a template name directly like below i.e. when I hard code it
<div ui-view="number1"></div>
It loads the template fully.
This is the dynamic model
<button ng-model="template_name" ng-value="number1">Button1</button>
<div ui-view="{{template_name}}"></div>
{{template_name}}
The above does not load the template as I expected. but it shows the string number1 when
the button is clicked
What can I do for it to load the template....
This is my controller
.state('parent',{
url: '/newtemplate',
views:{
'':{
templateUrl: "parent.tpl",
contoller:"controller",
},
'number1#parent':{
templateUrl:"number1.tpl",
contoller:"formcontroller"
},
'number2#parent':{
templateUrl:"number2.tpl",
contoller:"formcontroller"
},
'number3#parent':{
templateUrl:"number3.tpl",
contoller:"formcontroller"
}
}
})
Strange enough when I used the dot notation it did not work so I have to use the absolute naming method.
I also noticed that when I added the nested views as shown above the time it takes before the template gets loaded take a very long time.
Please I would appreciate any help which can allow me to load a nested view at runtime (possibly very fast)
Expecting more answer
I still hope that the I can make use of ui-view/ui-router because of the ability to make use of controller.
I'm not sure you can use uiView to load html dynamically.
I would try another possible solutions:
Use directives
Using ngInclude
I'll leave you an example with ngInclude: https://next.plnkr.co/edit/M5hl71mXdAGth2TE?open=lib%2Fscript.js&deferRun=1&preview
So I'm following this tutorial:
http://www.tinywall.info/2012/02/change-browser-url-without-page-reload-refresh-with-ajax-request-using-javascript-html5-history-api-php-jquery-like-facebook-github-navigation-menu.html
My goal is to load the actual content of my views and change the browsers URL without reloading the page. However, because I'm using CodeIgniter as a framework of my application, I can't get it to work properly. I have a controller where I'm loading all of my Dashboard's views, ones I want display inside my div called content_container.
The problem is that every time I click another anchor tag to get different view to load through ajax request, it adds another "dashboard" -in my url and of course it doesn't display the view after that. So after couple clicks, the URL would look something like this: "dashboard/dashboard/dashboard/profile". I've tried to split the URL with Javascript, but that didn't help me.
One solution would be to create single controller for each view, but I consider it as a bad practice and the code is a lot more cleaner with just one controller to handle all the views.
Here's the controller:
<?php
class Dashboard extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->output->nocache();
$this->load->model('subject_model');
$this->load->model('user_model');
}
public function index()
{
$this->load->view('header');
$this->load->view('dashboard');
$this->load->view('footer');
}
public function users()
{
$data['users'] = $this->user_model->getUsers();
$this->load->view('staff_users', $data);
}
public function lomake()
{
$this->load->view('lomake');
}
public function profile()
{
$data['userinfo'] = $this->user_model->getUserInformationById($this->session->userdata('user_id'));
$this->load->view('myprofile', $data);
}
public function subjects()
{
$this->load->view('subjects');
}
}
?>
And here's my dashboard view (part of it):
<aside id="left_control_panel">
<ul id="left_control_links">
<li>
Home
</li>
<li>
Subjects
<span class="list_total_count"><?=$total_subjects?></span>
</li>
<li>
Query
</li>
<?php if($this->session->userdata('user_type') == 'admin'):?>
<span class="left_control_heading">User management</span>
<li>
Users
<span class="list_total_count"><?=$total_users?></span>
</li>
<li>
<a class="add_user" href="add_user">Add User</a>
</li>
<?php endif;?>
<span class="left_control_heading">Account management</span>
<li>
My Profile
</li>
<li>
Sign Out
</li>
</ul>
</aside> <!-- end of left_control_panel -->
<div id="wrapper_loggedin">
<div class="content_container">
<! -- I will display all the data from different views in here -->
</div>
</div> <!-- end of wrapper_loggedin -->
And finally the JS part which can also be found in the tutorial:
$(function(){
$("a[rel='tab']").click(function(e){
//e.preventDefault();
pageurl = $(this).attr('href');
$.ajax({url:pageurl+'?rel=tab',success: function(data){
$('.content_container').html(data);
}});
//to change the browser URL to 'pageurl'
if(pageurl!=window.location){
window.history.pushState({path:pageurl},'',pageurl);
}
return false;
});
});
/* the below code is to override back button to get the ajax content without reload*/
$(window).bind('popstate', function() {
$.ajax({url:location.pathname+'?rel=tab',success: function(data){
$('.content_container').html(data);
}});
});
Application/config/routes.php
$route['dashboard'] = 'dashboard/index';
$route['dashboard/(:any)'] = 'dashboard/$1';
well, with my specific situation I had thousands of products organized in categories and sub categories. Well..thats a ton of urls and controllers to write. so what i did was make a category template, a sub category template and a product page template. then made routes like below in my application/config/routes.php file:
$route['products'] = 'products/index';
//so i know now they are on a category page and $1 is the name of the category.
//i can go query my db and get all subcategorys and the products under each now.
$route['products/(:any)'] = 'products/category/$1';
//the 1 and 2 here are category and subcategory from the url. so i know from this to
//use these in my query to grab all products in this category and subcategory.
$route['products/(:any)/(:any)'] = 'products/subcategory/$1/$2';
//i know this is gonna be a product page. and i know the category, the sub category and the product name. in this case all i really need is the product name since there is only one product with that name.
$route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3';
in your situation you can do the same. use your urls, your taking the time to build them so use them. in javascript you can send them back to your controllers via 'window.location.pathname'; all you have to do is split it up and you can use the same mentality to load a page and know exactly where you are at.
Also, in your ajax url property make sure your url is either an absolute url, or it references the root first. I think i know what your issue is. you are using a url like "users/dashboard" in your url property when it should be "/users/dashboard" you need to always go to the root and get the controller, otherwise it uses the url and will always take on the "users/dashboard" to the current url you are on. So if you are on "users/dashboard" and go load it again, your actually telling it to load "/users/dashboard/users/dashboard" and this becomes an infinite loop. Just put a backslash in front of your url and it will always reference the root.
I just did this very same thing. The way I did it was first make a dynamic route to always point to the same controller. $route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3'; etc. then anytime your page is loaded via a url (if someone puts in a specific url) you will still get content (bookmarks still work, you can send specific urls to people etc). Then what I did was every link that changed content also applied a data attribute to build the url out, i would also use those to pass back to the same controller. That controller also checks if the request is coming from an ajax request or not...if it is, you just load the page content...if it isnt then load the full template. its really not that hard and you actually almost have what i have. I think you are over thinking it. But the first thing i would do is make sure going to every page with the url works first. then try to get the ajax part working. The key is to detect if the request is coming from ajax or not within your controller. Then you can differentiate the two.
Also, I would strongly recommend you reading the user guide. The routes are usually one of the first thing you should cover when you start building projects with Codeigniter.
http://ellislab.com/codeigniter/user-guide/general/routing.html
Answering your question on the core controller. The answer is yes, you create a controller inside your core folder. It has to have a specific name. In your application/config/config.php file you should have:
$config['subclass_prefix'] = 'MY_';
This defines your prefix to any extended core controllers, models or system classes. Most Codeigniter system classes can be extended and you can overwrite properties (variables) and methods (functions). In your case you would drop a file called MY_Controller.php in your application/core folder. In this controller you would approach it like any other controller you write with the idea to not have to keep rewriting the same code over and over again, or to change the way the default Controller operates. You should read up on how a php class is suppose to work and the purpose of using them. Codeigniter doesn't really use them the way that you are suppose to use a class, but they approached it with the MVC approach. Usually, a class is referenced to as an object. Think of a class as a Bear. A bear has weight, age, length, color, height. All of these are called "properties". A bear can also eat, drink, and hunt. Each of these are called "methods". A more detailed version of a bear would be a polar bear, grisly bear or panda bear. These could be children of the bear object (they would extend the Bear object). Any child object inherits its parents properties and methods. But their values and actions could differ. The polar bear is a different color, size, height than the panda bear but it still eats, drinks, and hunts. Some properties and methods might not change, so there is no reason to rewrite those in the child classes. So in your case, the core controller can handle things that every page does. It can verify sessions, track a users activity, define global error messages etc. Ive even gone so far as to create a method in my core controller that loads my template pieces together (header, footer, sidebar, content) so i didn't have to keep stacking $this->load->view() when i was loading pieces of my template. All I had to do was pass the content and data that needed to be passed and it loaded my template everywhere. You also need to understand how the __construct works. You can think of the __construct as a function that always runs first before your page loads. so by defining a construct in your core controller you can then fill in data automatically. Browse these links as they go into a deeper explanation on how to use these features and shows examples.
http://ellislab.com/codeigniter/user-guide/general/core_classes.html
http://www.php.net/manual/en/language.oop5.php
Please give me a up vote if this guided you in the right direction :) Im trying to build up my points and profile and eventually link my account up to my website so it proves my plethora of php & codeigniter knowledge to any future employees.
This may seem like a dumb question. But I have no idea if it can be done. So before I start the process of making a portfolio site, I would like some pointers. Otherwise, I will just go with another design.
My question:
When using the ascencor.js plugin, everything on my site is in one file. I will therefor never go to a new url, like /contact or /about.
But then I wondered, what about google?
All of my content would be put inside different different classes, but in the same file:
<div class="floor floor-1">
<span class="text">Floor 1</span>
</div>
<div class="floor floor-2">
<span class="text">Floor 2</span>
</div>
Check the example here: http://rplambech.dk/ascencor/
So yeah, with this method, I will never change the url, so I can therefor only index one page.
Is there a way that I can change the URL without updating the site? And will I be able to go to http://rplambech.dk/ascencor/floor5 for example?
In case it's not possible, can I then at least overwrite the title of the page, each time I click to a new "page". With some PhP for example.
Or should I just go with a completely different approach? :)
From the context of your question, and its comments, you're looking for the term single-page-application.
There are many ways of doing this, some of them make use of the history object in order to support the browser's "back" and "forward" buttons.
I'd recommend you to do a search of the term "single page application" and in the meantime examine some (or all) of the following frameworks (they will ease your development and make your life easier instead of dealing with # and nasty low-level ajax calls:
backbone.js
angularJS
ember.js
It can be done using hash links, originally designed to jump to a certain div on the page are now often used to load dynamic pages on a single page
so you could link to http://rplambech.dk/ascencor/index.html#floor5 for example
and then have some javascript like
var loc = location.hash.split("#")[1];
then
if(loc == 'floor5'){
//execute goto floor 5 code
}
Using history.pushState with HTML5 as stated here.
<script type="text/javascript">
var stateObj = { foo: "bar" };
function change_my_url()
{
history.pushState(stateObj, "page 2", "bar.html");
}
var link = document.getElementById('click');
link.addEventListener('click', change_my_url, false);
</script>
URL:
<a href="#" id='click'>Click to change url to bar.html</a>
No you can't change the URL without going to the server.
JQuery does however have a cool page loader that will load a page.
How to put a whole html page in a div using jquery?
You cannot change the url "/ascencor" to "/ascensor/floor5" without refreshing the page.
But you can change to "/ascensor/#floor5" (added hash sign). I suggest you try out angularjs for more information.
If you're at a location like this...
http://www.domain.com/index.html
... and you have a link that points to the same location...
My Link
... then clicking on the link does nothing. Normally you would be redirected to the page as normal; a handy way to refresh the page (without doing a full refresh).
I've traced the culprit of this odd behaviour to AngularJS.
Observe the following example:
<body>
Sample Link
<script>
var SampleApp = angular.module("SampleApp", []);
</script>
</body>
http://jsfiddle.net/7vqD9/
By clicking on the link the browser tries to go to the same location (because of a blank href). This is normal.
Now let's activate Angular:
<body ng-app="SampleApp">
Sample Link
<script>
var SampleApp = angular.module("SampleApp", []);
</script>
</body>
http://jsfiddle.net/7bEp3/
Clicking on the link does nothing.
Why does AngularJS break links in this way? Is there any obvious reason that I'm missing?
Why does Angular prevent classic behavior of href?
From Mastering web component with AngularJs:
AngularJS comes pre-bundled with the a directive, which prevents
default actions on links when the href attribute is omitted. This
allows us to create clickable elements using the a tag and the
ng-click directive. For example, we can invoke the atag as follows:
<a ng-click='showFAQ()'>Frequently Asked Questions</a>
Having the a tags without a default navigation action is handy, as
several CSS frameworks use the a tags to render different types of
visual elements, where a navigation action doesn't make much sense.
For example the Twitter's Bootstrap CSS framework uses the a tags to
render headers in tabs and accordion components.
Keyword to retain is: "handy"
Angular overrides the a tag: https://github.com/angular/angular.js/blob/master/src/ng/directive/a.js
The lines to note here are:
// if we have no href url, then don't navigate anywhere.
if (!element.attr('href')) {
event.preventDefault();
}
Angular does this because of ngHref, which sets the href only after angular and scope are fully loaded, thus preventing the user from accidentally going to /{{pageUrl}}/.
If you want to reload the page, you should look at the $location service provided by Angular.
I'm just getting my feet wet with Ember.js, and I've hit something that I'm sure I'm not understanding.
I've got a selected object controller. It has content, which is an Ember.Object, which is the currently selected model. The model has a property (isDirty), and basically I'd like my save button on my form to be enabled only when the object is dirty and needs to be saved.
I've managed to bind up the form just fine, but the isEnabledBinding property on the save button is either not doing anything or I'm not hooking up the binding properly.
I've prepared a jsfiddle demonstrating my basic set up.
http://jsfiddle.net/blargity/fqc73/1/
How do I get the button to be enabled only when isDirty is true? The bindings should also work if the content property on the selected object controller changes.
I found a way to do this without using the now-deprecated Ember.Button.
In the handlebars template:
<button {{action "save" target="controller"}} {{bindAttr disabled="view.isNotDirty"}}>Save</button>
In the view:
isNotDirty: function(){
return !this.get('controller.content.isDirty')
}.property('controller.content.isDirty').cacheable()
(With the version of Ember I have, Ember.Binding.not does not exist. Maybe I need to update, but the docs don't show it either so perhaps it was actually removed.)
The problem is that there is no isEnabled property on Ember.Button. You need to bind to the disabled property.
One possibility is to create a custom Ember.Button which handles this for you, see http://jsfiddle.net/LabpW/.
Handlebars:
{{#view App.SaveModelButton modelBinding="model"}}Save{{/view}}
JavaScript:
App.SaveModelButton = Ember.Button.extend({
disabledBinding: Ember.Binding.not('model.isDirty')
});
The used Ember.Binding.not is just a shortcut for writing your own computed property, which would look like this:
App.SaveModelButton = Ember.Button.extend({
disabled: function() {
return !Ember.getPath(this, 'model.isDirty');
}.property('model.isDirty').cacheable()
});
I also refactored your code a bit:
You mixed create and extend: use create for instances and extend for classes. There is a good blog post about this
It's kind of a convention to use lowerCase for instances and UpperCase for classes, so it should be App.controller instead of App.Controller