Альтернативный способ использования eval () для создания динамической переменной внутри for () при запуске jQuery? - PullRequest
1 голос
/ 24 августа 2011

Я довольно новичок в JS и не очень знаком с jQuery, но я бы хотел попробовать динамически вызывать функцию мультиизображения slimbox .

Например,на моем веб-сайте есть фотолайдер, который случайным образом перебирает 3 изображения, и я бы хотел, чтобы slimbox показал еще 2 изображения для первого и еще 1 для последнего.Это означает, что Slimbox будет отображать в общей сложности 6 изображений в слайд-шоу.

Так что, если вам это нужно, вот подробный обзор: когда пользователь посещает мой сайт, он увидит блок div, который показывает 1 изображение за раз.Изображение на фотослайдере будет повернуто к следующему (из 3 случайно загруженных).Когда пользователь нажимает на изображение, он запускает слимбокс (облегченный лайтбокс), и на экране появляется увеличенное слайд-шоу (затемняя фон).Через Slimbox пользователь будет видеть до 6 циклов изображения.

Чтобы создать динамическую переменную, я попытался использовать EVAL в цикле FOR, но это не удалось при запуске jQuery.EVAL работает вне цикла, хотя.Я не уверен, какую другую функцию использовать вместо этого.Давайте углубимся в код ...

Вызов Slimbox через JS:

// usage as shown for multi-image slideshow.  yes, there are arrays within an array
jQuery.slimbox([["image","desc"], ["image","desc"], ["image","desc"]], startAtImage);

// or simplified further
jQuery.slimbox([[array1], [array3], [array2]], startAtImage);

// after appending the images to select the first and last images 
jQuery.slimbox([[array1], [array4], [array5], [array3], [array2], [array6]], startAtImage);

Вот моя попытка динамического вызова функции Slimbox:

var imgAlbum = "summer";

var arrayGiven = [1,3,2];       // randomized image order given

var img1 = [4,5];               // registering images to be appended -- aiming for [1,4,5]
var img2 = [6];                 // registering images to be appended -- aiming for [2,6]

var desc1 = "Description #1";   // unique descriptions
var desc2 = "Description #2";
var desc3 = "Description #3";
var desc4 = "Description #4";
var desc5 = "Description #5";
var desc6 = "Description #6";

var arrayExtended = arrayGiven;

for(var i=1; i<=3; i++){                                            // cycle through arrayGiven and append images
    var imgLocate = i;
    var imgAtIndex = jQuery.inArray(imgLocate,arrayExtended);       // locating array index number of a specific image.  if imgLocate = 1, then imgAtIndex = 0 , if 2 then 4, and so forth
    var imgAfter = imgAtIndex + 1;                                  // allows appending to selected image at index

    eval("var imgCurrent = img" + imgLocate + ";");                 // creating dynamic variable
    if(imgCurrent != null){
        arrayExtended.splice(imgAfter, 0, imgCurrent); 
    }       
}   // alert(arrayExtended) should be [1,4,5,3,2,6]

for(var i=1; i<=arrayExtended.length; i++){
    var imgLocate = i;

    eval("var array" + imgLocate + " = ['img/" + imgAlbum +  "/" + imgLocate + ".jpg',desc" + imgLocate + "];");    // if imgLocate = 1, then var array1 = ['img/summer/1.jpg',desc1];
                                                                                                                    // array1 array2 array3 array4 array5 array 6 ... now defined
}

var arrayMain = [];

for(var i=1; i<=arrayExtended.length; i++){                         // must wait for arrays to be built before adding to arrayMain
    var atIndex = i - 1;

    var imgAtIndex = jQuery.inArray(imgLocate,arrayExtended);       // if imgLocate = 1, then imgAtIndex = 0 , if 2 then 4

    eval("arrayMain.push('[' + array" + arrayExtended[atIndex] + " + ']');");
}

var imgClicked = 0;                                                 // clicked on image within arrayExtended index 0
var startAtImage = imgClicked;                                      // slimbox slideshow will start on 1.jpg

jQuery.slimbox("[" + mainArray + "]",startAtImage);

И, наконец, надеемся на следующий результат:

jQuery.slimbox([["img/summer/1.jpg","Desciption #1"], ["img/summer/4.jpg","Desciption #4"], ["img/summer/5.jpg","Desciption #5"], ["img/summer/3.jpg","Desciption #3"], ["img/summer/2.jpg","Desciption #2"]], ["img/summer/6.jpg","Desciption #6"], 0);

Любая помощь или совет будет высоко ценится!Можно многому научиться.

Обновлено 8-26-11 Изменена структура на основе советов.Также добавлено больше изображений и групп в массив для лучшей иллюстрации необходимой функциональности.При попытке вызвать группы изображений (1, 2, 7) из объекта img возникают ошибки:

        var imgAlbum = "summer";

        var arrayGiven = [1,3,2,7,11];      // randomized image order given

        var img = {
          1: [4,5],
          2: [6],
          7: [10,8,9]
        };

        var desc = {
          1: 'Description #1',
          2: 'Description #2',
          3: 'Description #3',
          4: 'Description #4',
          5: 'Description #5',
          6: 'Description #6',
          7: 'Description #7',
          8: 'Description #8',
          9: 'Description #9',
          10:'Description #10',
          11:'Description #11'
        };

        var arrayExtended = arrayGiven.slice();

        for(var i=1; i<=arrayGiven.length; i++){                                        
            var imgLocate = i;
            var imgAtIndex = jQuery.inArray(imgLocate,arrayExtended);       
            var imgAfter = imgAtIndex + 1;                                  
            var imgCurrent = img[imgAfter];

            if(imgCurrent != null){
                arrayExtended.splice(imgAfter, 0, imgCurrent); 
            }       
            //alert(imgCurrent);    // shows 4,5 undefined undefined undefined undefined
        }   //alert(arrayExtended);// shows 1,4,5,3,2,6,7,10,8,9,11
        var imgArray = {};
        for(var i=1; i<=arrayExtended.length; i++){
            var imgLocate = i;
            var atIndex = i - 1;

            imgArray[imgLocate] = ['imgs/'+imgAlbum+'/'+imgLocate+'.jpg', desc[imgLocate]];
        }

        var mainArray = [];

        for(var i=1; i<=arrayExtended.length; i++){                         
            var imgLocate = i;                  
            var atIndex = i - 1;

            mainArray.push(imgArray[arrayExtended[atIndex]]);   
            //alert(imgArray[arrayExtended[atIndex]]); // shows (simplified) 1.jpg,Desc#1 undefined 3.jpg,Desc#3 2.jpg,Desc#2 undefined undefined

        }

        var imgClicked = 0;                                                 
        var startAtImage = imgClicked; 

jQuery.slimbox(mainArray,startAtImage);

Обновлено 8-30-11 ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ Исправлены примененные и добавлены рандомизаторы из производствакод.Результаты точны.Если вы планируете использовать рандомизатор, я рекомендую хранить добавляемые изображения вне диапазона getRandomArray, если вы не хотите видеть дубликаты.

Спасибо всем за вашу поддержку!

function getRandomArray(min,max){
            var A= [];
            while(max>= min) A.push(max--)    
            A.sort(function(){return .5- Math.random()});  
            return A;
        }
        var randomness = getRandomArray(1,11).slice();
        var leadingZeroArray = randomness.slice();
        leadingZeroArray.unshift("0");          // was needed for my project, but if removed, everything else will need to be re-adjusted

        var arrayGiven = randomness.slice();    // or you can plug in -> var arrayGiven = [1,3,2,7,11]; for original example

        var imgAlbum = "summer";
        var img = {
          1: [4,5],
          2: [6],
          7: [10,8,9]
        };
        var desc = {
          1: 'Description #1',
          2: 'Description #2',
          3: 'Description #3',
          4: 'Description #4',
          5: 'Description #5',
          6: 'Description #6',
          7: 'Description #7',
          8: 'Description #8',
          9: 'Description #9',
          10:'Description #10',
          11:'Description #11'
        };

        var arrayExtended = arrayGiven.slice();

        for(var i=0; i<arrayGiven.length; i++){                                         
            var imgLocate = arrayGiven[i]; 
            var imgAtIndex = jQuery.inArray(imgLocate,arrayExtended);       
            var imgAfter = imgAtIndex + 1;                                  
            var imgCurrent = img[imgLocate];

            if(imgCurrent != null){
                if(imgCurrent.length > 0){
                    for(var j=imgCurrent.length-1; j>-1; j--){
                        var imgMore = imgCurrent[j];
                        arrayExtended.splice(imgAfter, 0, imgMore); 
                    }
                }
                else{arrayExtended.splice(imgAfter, 0, imgCurrent); }
            }
        }   
        var imgArray = {};
        for(var i=1; i<=arrayExtended.length; i++){
            var imgLocate = i;
            var atIndex = i - 1;

            imgArray[imgLocate] = ['images/'+imgAlbum+'/'+imgLocate+'.jpg', desc[imgLocate]];
        }
        var mainArray = [];
        for(var i=1; i<=arrayExtended.length; i++){                         
            var imgLocate = i;                  
            var atIndex = i - 1;

            mainArray.push(imgArray[arrayExtended[atIndex]]);   
        }

        var imgClickedOn = 5;
        var imgAtIndex = jQuery.inArray(imgClickedOn,arrayExtended);

        jQuery.slimbox(mainArray,imgAtIndex);

Ответы [ 4 ]

3 голосов
/ 24 августа 2011

Вместо нескольких переменных для img используйте массив или объект.

var img = {
  1: [4,5],
  2: [6]
};

Тогда вместо eval("var imgCurrent = img" + imgLocate + ";"); вы можете сделать:

var imgCurrent = img[imgLocate];

Youможет сделать то же самое для:

eval("var array" + imgLocate + " = ['img/" + imgAlbum +  "/" + imgLocate + ".jpg',desc" + imgLocate + "];");

Создать объект и поместить туда массивы:

var desc = {
  1: 'Description #1',
  2: 'Description #2',
  3: 'Description #3',
  4: 'Description #4',
  5: 'Description #5',
  6: 'Description #6'
};
var imgArray = {};
imgArray[imglocate] = ['img/'+imgAlbum+'/'+imgLocate+'.jpg', desc[imgLocate]];

РЕДАКТИРОВАТЬ : Попробуйте изменить var imgLocate = i;внутри for(var i=1; i<=arrayGiven.length; i++){ до var imgLocate = arrayGiven[i];.

2 голосов
/ 24 августа 2011

Глобальные переменные являются членами объекта window, поэтому вы можете просто сделать:

var imgCurrent = window["img" + imgLocate];

Однако использование таких динамических имен переменных не является хорошей практикой.Вы должны просто поместить значения в массив:

var img = [
  [4,5],
  [6]
];

Теперь вы можете просто получить доступ к элементам массива:

var imgCurrent = img[imgLocate];

Обратите внимание, что индексы массива начинаются с 0, а не с 1.

1 голос
/ 25 августа 2011

Несколько быстрых заметок:

  1. Пожалуйста, не используйте eval().Очень, очень мало случаев, когда это необходимо, и это влияет на производительность и безопасность.

  2. Вы обнаружили, что в JavaScript нет «переменных переменных» (возможность получитьили установите переменную по имени), поэтому вам пришлось прибегнуть к eval().Когда вам нужно найти что-то из набора, не используйте кучу пронумерованных переменных.Вместо этого попробуйте массив или объект.

  3. Объекты в JavaScript не копируются при назначении их переменным.Строка

    var arrayExtended = arrayGiven;
    

    не делает копию arrayGiven - arrayExtended и является переменной, которая указывает на тот же массив.Таким образом, когда вы изменяете что-то в arrayExtended, оно также меняет это в arrayGiven.Если вам нужно скопировать массив в JavaScript, используйте .slice() без аргументов:

    var arrayExtended = arrayGiven.slice();
    

    Некоторые другие вещи в JavaScript, например объекты, сложнее скопировать.

  4. Что вы пытаетесь здесь сделать?(mainArray уже является массивом). Будет создана строка, представляющая собой «[», за которым следует строковое представление mainArray (каждый элемент в массиве, разделенный запятыми), за которым следует «]».Slimbox не будет знать, что с ним делать.

    jQuery.slimbox("[" + mainArray + "]",startAtImage);
    

    Если вы хотите обернуть что-то в массив, просто заключите в скобки, как вы это делали выше:

    [mainArray];
    

Я думаю, что ваша главная проблема "[" + mainArray + "]".С этими советами вы сможете заставить свой код работать (и без eval()).Но я хочу показать вам и мой подход к этой проблеме.Это ниже.

Я храню имена и описания всех изображений в массиве.Поскольку массивы в JavaScript (и во многих других языках программирования) начинаются с 0, а не с одного, я вычел одно из всех номеров изображений в массивах, которые указывают порядок.

var album = "summer",
    images = [
        [
            { name: "1", description: "Description #1" },
            { name: "4", description: "Description #4" },
            { name: "5", description: "Description #5" }
        ],
        [
            { name: "2", description: "Description #2" },
            { name: "6", description: "Description #6" }
        ],
        [
            { name: "3", description: "Description #3" }
        ]
    ],
    order = [0, 2, 1],
    startAtImage = 0,
    slimboxImages = Array.prototype.concat.apply([], order.map(function(id){ return images[id]; }))
        .map(function(image){
            return [ 'img/' + album + '/' + image.name + '.jpg', image.description];
        });

jQuery.slimbox(slimboxImages, startAtImage);
0 голосов
/ 24 августа 2011

по любой причине, которую вы не можете просто сделать

    var imgCurrent = 'img' + imgLocate;

? По сути, это НИКОГДА не хорошая идея динамически генерировать / выполнять код из скрипта. Его практически невозможно отладить, и вы даже не делаете ничего, что нельзя сделать БЕЗ eval.

...