I'm familiar with using something like:
$scope.gotoBottom = function(){
$location.hash('bottom');
$anchorScroll();
}
and this works.. yet what I'm seeing is an issue when retrieving data that's being used in an ng-repeat and attempting to resize when that data comes in.
Example (in controller):
users.get({userList:$routeParams.conversationId}, function(data){
$scope.userList = data;
$scope.gotoBottom();
})
The gotoBottom method is firing to fast, while the ng-repeat is looking on $scope.userList and buidling it's table based off that.
I want to be able to toggle gotoBottom after that list has been remade (or whenever it's modified). Is there a better way to achieve this?
Thank you!
You can use $watch listener to fire gotoBotton when an AngularJs variable change.
$scope.ActivityList = new Array();
$scope.$watch("ActivityList", function () {
$scope.$evalAsync(function () {
$scope.DoSomething();
});
}, true);
$scope.DoSomething = function () {
$(function () {
//$scope.gotoBottom();
});
};
Also you can run scrolling bottom after page is loaded
angular.element($window).bind('load',
function() {
var element = document.getElementById("messages-list").lastElementChild;
element.id = "bottom";
/*-------------*/
$location.hash('bottom');
$anchorScroll();
}
I've done a lot of reading over the last few years trying to become proficient with JavaScript and it's frameworks. It seems that most texts either teach the rudiments of ajax, loading something into an empty element, or they assume you know what your doing and glance over the data handling portion. I've developed my own methods over time, but having nothing to compare them too. I don't know how efficient they are. When building a ajax based site I typically use jquery and history.js and my code is as follows.
function updateContent(state){
var theUrl = state.data.urlPath; //the url of what needs ajaed in
$('#container #content').fadeOut(500, function(){ //fade out old content
var newContent = {};
newContent.load(theUrl + ' #content', function(){ //load new content into object
newContent.hide(); //hide it so it can be faded in
$('#container').html(newContent); //replace content in container
newContent.fadeIn(500); //fadein content
});
});
}
var History = window.History;
if (History.enabled) {
var State = History.getState();
History.pushState({urlPath: window.location.href}, $("title").text(), State.urlPath);
} else {
return false;
}
History.Adapter.bind(window, 'statechange', function() {
updateContent(History.getState());
});
$(document).on('click', 'a', function(evt){
var testSite = /http:\/\/www.example.com(\/)?/ //regex to test if is local link
var theUrl = $(this).attr('href'); //the url of the clicked link
if(testSite.test(theUrl)){
evt.preventDefault();
History.pushState({urlPath: theUrl}, title, theUrl);
}
});
This is the basics of my code. I feel it is inefficient particularly when the back button is used. When going back the content has to be reloaded. Is there a more efficient way to do this?
Having some issues with a function in Knockout.js. Basically it is a menu where the first menu item "Översikt" should fetch a JSON array and populate the view.
The knockout code:
self.ongoingAuctions = ko.observableArray([]);
self.getOngoingAuctions = function(data) {
$.getJSON("assets/json/auctions.json", function(data) {
self.ongoingAuctions(data);
});
}
My click binding:
The problem is that this only works the first time I click on the menu item. The JSON doesn't get fetched the second, third, n:th time.
What am I doing wrong? Or have I misunderstood something?
Thanks in advance!
I have shared this fiddle for you that shows something else is wrong in your code that you havent not specified in the question:
It makes the call to the non existing json (in my case) every time you click
JS Fiddle to working code
var viewModel = function(){
var self = this;
self.ongoingAuctions = ko.observableArray([]);
self.getOngoingAuctions = function(data) {
$.getJSON("assets/json/auctions.json", function(data) {
self.ongoingAuctions(data);
});
}
self.setHeadline = function(){
console.log('set headline')
}
self.headline = function(){
console.log('headline');
}
}
var myVm = new viewModel();
ko.applyBindings(myVm);
I'm using this Fx.Slide script in my site:
var togglers = $$('.toggler'), expanders = $$('.expandable');
togglers.each(function(toggler, index){
var fx = new Fx.Slide(expanders[index]).hide();
toggler.addEvents({
click: function(e){
e = new Event(e);
fx.toggle();
e.stop();
return false;
}
});
});
Which is working just fine. What I wasn't able to do is get the current state of the slide so I can assign some open/closed icons on the toggler element.
Thanks!
Hi you can use the attribue open of the slider:
if(fx.open){
//whatever you need to do
}else{
//whatever you need to do
}
i think you need put the slider in an array to be able to access them later...
hope this helps
You could even store the Fx.Slides in the togglers themselves, if you don't want to keep a separate array.
[...]
togglers.each(function(toggler, index){
var fx = new Fx.Slide(expanders[index]).hide();
expanders[index].store('slide',fx)
toggler.addEvents({
[...]
});
});
Then later you can check the status, like mklfarha said:
if(expanders[index].retrieve('slide').open){
//do some stuff
}
I'm writing a simple jQuery plugin, but I'm having trouble being able to use multiple instances on a page.
For instance, here is a sample plugin to illustrate my point:
(function($) {
$.fn.samplePlugin = function(options) {
if (typeof foo != 'undefined')
{
alert('Already defined!');
} else {
var foo = 'bar';
}
};
})(jQuery);
And then if I do this:
$(document).ready(function(){
$('#myDiv').samplePlugin({}); // does nothing
$('#myDiv2').samplePlugion({}); // alerts "Already defined!"
});
This is obviously an over-simplified example to get across the point. So my question is, how do I have two separate instances of the plugin? I'd like to be able to use it across multiple instances on the same page.
I'm guessing that part of the problem might be with defining the variables in a global scope. How can I define them unique to that instance of the plugin then?
Thank you for your guidance!
I have the very same problem but i find a very handy solution i´ll post it for someone who may have this problem
when you define your variables insinde the plugin you could use the .data() to store all the variables you define
like this
(function($) {
$.fn.samplePlugin = function(options) {
var base = this;
this.foo // define foo
// do stuff with foo and other variables
// Add a reverse reference to the DOM object
this.data("pluginname", base);
};})(jQuery);
And when you want to use the same foo variable you should retrive the reference with this:
base = this.data("pluginname");
base.foo
Hope it helps
Logan
html:
<code class="resize1">resize1</code>
<code class="resize2">resize2</code>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('.resize1').ratiofix({message:'resize1'});
$('.resize2').ratiofix({message:'resize2'});
});
</script>
I have found 2 solutions - the first one is jquery widget factory
http://jqueryui.com/widget/
js code:
$.widget("custom.ratiofix",{
options:{
message:"nothing"
},
_create:function (){
var self=this;
this.setListeners();
},
setListeners:function (){
var self=this;
$(window).on('resize',$.proxy(self.printMsg,self));
},
printMsg:function (){
console.log(this.options.message);
}
});
And the second (without widget factory):
(function ($){
var Ratiofix = {
init: function(options, elem) {
this.options = $.extend({},this.options,options);
this.elem = elem;
this.$elem = $(elem);
this.setListeners();
return this;
},
options: {
message: "No message"
},
printMsg: function(){
console.log(this.options.message);
},
setListeners:function (){
var self=this;
this.$elem.on('click',function (){
console.log(self.options.message);
});
$(window).on('resize',$.proxy(self.printMsg, self));
}
};
$.fn.ratiofix=function (options){
this.init= function(options, elem) {
this.options = $.extend({},this.options,options);
this.elem = elem;
this.$elem = $(elem);
return this;
};
if ( this.length ) {
return this.each(function(){
var ratiofix = Object.create(Ratiofix);
ratiofix.init(options, this);
$.data(this, 'ratiofix', ratiofix);
});
}
};
})(jQuery);
In both cases plugins work separately and have own settings. In my case - 2 widgets listen to window resize and print to console own options.message
I'm not sure what you mean by having more than one instance of a plugin. A plugin would be available to use on any element.
This comment doesn't clarify much for me:
So say that it was a plugin that took
a "color" parameter and turned the
object into that color. Well, in that
case you'd need multiple instances, as
you're dealing with more than one page
element turning more than one color.
In this case, you would pass in different colors are arguments as needed:
$('div#foo').makeColor('red');
$('div#bar').makeColor('blue');
Each time you call the plugin, it will use whatever arguments you give it. The plugin isn't a class that needs instances.
Just throwing my solution in here:
(function ($){
$.fn.plugin = function (options){
var settings = $.extend({}, $.fn.plugin.defaults, options);
settings.that = $(this);
$.fn.plugin.init (settings);
};
$.fn.plugin.defaults = { objval: 'default' };
$.fn.plugin.init = function (settings){
settings.that.val (settings.objval);
};
}( jQuery ));
$('#target1').plugin ({objval: 'not default'});
$('#target2').plugin ();
DEMO
The settings variable is isolated every time you initialize the object.
To answer your question directly, you can use jQuery.noconflict() to avoid namespace collisions and thus potentially have multiple instantiations on a page..
var $j = jQuery.noConflict();
// Use jQuery via $j(...)
$j(document).ready(function() {
// etc
check here
But I question your design. Why are you writing a plugin that appears to not operate on a jQuery wrapped set ? .. Plugins should be written to assume they are operating on a jQuery array held in 'this'. In which case any state can be stored in each of the items being acted upon... But maybe you are building something different?
Please review this page
instead of writing this
$("#divid1").samplePlugin();
$("#divid2").samplePlugin();
you can do this way
$.plugin('samplePlugin1', samplePlugin);
$("#divid1").samplePlugin1();
$.plugin('samplePlugin2', samplePlugin);
$("#divid2").samplePlugin2();
You can have much details from here
http://alexsexton.com/?p=51
You need to use this.foo instead of var foo, so that the variable is only related to the current object.
This worked a treat for me! I had specific parameters for which pages/places I wanted to run a plugin and was able to achieve success by using a simple if statement. Hope this helps someone!
<!-- Begin JQuery Plugin Foo -->
<script src="js/foo_fun.js"></script>
<?php
if(substr_count(strtolower($currentUrl),"member")>0)
{
?>
<script>
$(document).ready(function(){
$('#vscroller').vscroller({newsfeed:'news_employee.xml', speed:1000,stay:2000,cache:false});
});
</script>
<?php
}
else
{
?>
<script>
$(document).ready(function(){
$('#vscroller').vscroller({newsfeed:'news_company.xml', speed:1000,stay:2000,cache:false});
});
</script>
<?php
}
?>
<!-- End JQuery Foo-->
I had the same problem : how to use many instances of a plugin on only one form ?
The usual way fails because in fact, the instance is not an instance of the plugin : it is an instance of jQuery.
So, if more than one element is defined to be managed by a plugin, each definition overrides the previous parameters.
It was necessary to have a look on the problem from another side.
A plugin is usually made to react on a specific event for a specific element. e.g.. onclick on a button, or when the mouse is over the element.
In my case, I had to use an autocomplete plugin for a city field, but my form has 5 tabs and in total 4 fields for the cities for 4 different parts of the information to be collected.
For each fields, parameters are specifics.
By the way, I've realised iI don't need to have the plugin active everytime : just on the appropriate event on the field is enough.
So I had an idea : an event manager for each element. When the event appends, so I define the plugin action.
Some code will be more efficient to explain : imagine you have 3 div blocks and your plugin must change the colours, but with specifics colours depending on which div is affected.
$(document).ready(function(){
// Wich elements are affected by the plugin
var ids = ['myDiv1','myDiv2','myDiv3'];
// foe each one :
for (v in ids)
{
//define from an event :
$('#'+ ids[v]).focus(function()
{
// depending which id is active :
var aParams, idDiv = $(this).attr('id');
// Choosing the right params
switch(idDiv)
{
case 'myDiv1':
aParams = {'color': '#660000', 'background-color': '#0000ff'};
break;
case 'myDiv2':
aParams = {'color': '#006600', 'background-color': '#ff00ff'};
break;
case 'myDiv3':
aParams = {'color': '#000066', 'background-color': '#ff0000'};
break;
default:
aParams = {'color': '#000000', 'background-color': '#ffffff'};
};
// Defining the plugin on the right element with the right params
$(this).myPlugin(
{
colors: aParams
});
});
}
});
And this works fine.
Sorry if my English is not perfect - I hope you understand well.