Обнаружение изменений данных в формах с использованием jQuery

Для подготовленных операторов SQLite в Android есть SQLiteStatement . Подготовленные заявления помогают ускорить работу (особенно для операторов, которые нужно выполнять несколько раз), а также помогают избежать атак на атаку. См. в этой статье для общего обсуждения подготовленных операторов.

SQLiteStatement предназначен для использования с операторами SQL, которые не возвращают несколько значений. (Это означает, что вы не будете использовать их для большинства запросов.) Ниже приведены некоторые примеры:

Создать таблицу

String sql = "CREATE TABLE table_name (column_1 INTEGER PRIMARY KEY, column_2 TEXT)";
SQLiteStatement stmt = db.compileStatement(sql);
stmt.execute();

execute() не возвращает значение, поэтому его следует использовать с CREATE и DROP, но не предназначено для использования с SELECT, INSERT, DELETE и UPDATE, потому что они возвращают значения. (Но см. этот вопрос .)

Вставить значения

String sql = "INSERT INTO table_name (column_1, column_2) VALUES (57, 'hello')";
SQLiteStatement statement = db.compileStatement(sql);
long rowId = statement.executeInsert();

Обратите внимание, что executeInsert() , а не execute(). Конечно, вы не хотели бы всегда вводить одни и те же вещи в каждой строке. Для этого вы можете использовать привязки .

String sql = "INSERT INTO table_name (column_1, column_2) VALUES (?, ?)";
SQLiteStatement statement = db.compileStatement(sql);

int intValue = 57;
String stringValue = "hello";

statement.bindLong(1, intValue); // 1-based: matches first '?' in sql string
statement.bindString(2, stringValue);  // matches second '?' in sql string

long rowId = statement.executeInsert();

Обычно вы используете подготовленные инструкции, когда хотите быстро повторять что-то (например, INSERT). Подготовленный оператор делает так, что SQL-запрос не должен анализироваться и скомпилироваться каждый раз. Вы можете ускорить еще больше, используя транзакции . Это позволяет сразу применить все изменения. Вот пример:

String stringValue = "hello";
try {

    db.beginTransaction();
    String sql = "INSERT INTO table_name (column_1, column_2) VALUES (?, ?)";
    SQLiteStatement statement = db.compileStatement(sql);

    for (int i = 0; i < 1000; i++) {
        statement.clearBindings();
        statement.bindLong(1, i);
        statement.bindString(2, stringValue + i);
        statement.executeInsert();
    }

    db.setTransactionSuccessful(); // This commits the transaction if there were no exceptions

} catch (Exception e) {
    Log.w("Exception:", e);
} finally {
    db.endTransaction();
}

Ознакомьтесь с этими ссылками для получения более подробной информации о транзакциях и ускорения вставки баз данных.

Обновить строки

Это базовый пример. Вы также можете применить понятия из раздела выше.

String sql = "UPDATE table_name SET column_2=? WHERE column_1=?";
SQLiteStatement statement = db.compileStatement(sql);

int id = 7;
String stringValue = "hi there";

statement.bindString(1, stringValue);
statement.bindLong(2, id);

int numberOfRowsAffected = statement.executeUpdateDelete();

Удалить строки

Метод executeUpdateDelete() также может использоваться для операторов DELETE и был введен в API 11. См. этот Q & amp; A .

Вот пример.

try {

    db.beginTransaction();
    String sql = "DELETE FROM " + table_name +
            " WHERE " + column_1 + " = ?";
    SQLiteStatement statement = db.compileStatement(sql);

    for (Long id : words) {
        statement.clearBindings();
        statement.bindLong(1, id);
        statement.executeUpdateDelete();
    }

    db.setTransactionSuccessful();

} catch (SQLException e) {
    Log.w("Exception:", e);
} finally {
    db.endTransaction();
}

Query

Обычно, когда вы запускаете запрос, вы хотите получить курсор назад с большим количеством рядов. Однако это не то, что SQLiteStatement. Вы не запускаете с ним запрос, если только вам нужен простой результат, например количество строк в базе данных, которое вы можете сделать с помощью simpleQueryForLong()

String sql = "SELECT COUNT(*) FROM table_name";
SQLiteStatement statement = db.compileStatement(sql);
long result = statement.simpleQueryForLong();

Обычно вы запускаете метод query() для SQLiteDatabase , чтобы получить курсор.

SQLiteDatabase db = dbHelper.getReadableDatabase();
String table = "table_name";
String[] columnsToReturn = { "column_1", "column_2" };
String selection = "column_1 =?";
String[] selectionArgs = { someValue }; // matched to "?" in selection
Cursor dbCursor = db.query(table, columnsToReturn, selection, selectionArgs, null, null, null);

Для получения более подробной информации о запросах см. этот ответ .

23
задан Peter Mortensen 8 January 2018 в 13:21
поделиться

9 ответов

Вы можете привязать событие Change ко всем входам и пометить переменную как true. Вот так.

var somethingChanged = false;
$(document).ready(function() { 
   $('input').change(function() { 
        somethingChanged = true; 
   }); 
});

Но имейте в виду, что если пользователь что-то изменит, а затем вернется к исходным значениям, он все равно будет помечен как измененный.

ОБНОВЛЕНИЕ: Для определенного div или набора полей. Просто используйте идентификатор для данного набора полей или div. Пример:

var somethingChanged = false;
$(document).ready(function() { 
   $('#myDiv input').change(function() { 
        somethingChanged = true; 
   }); 
});
43
ответ дан Jose Basilio 8 January 2018 в 13:21
поделиться

.live в настоящее время устарела и заменена на .on:

var confirmerSortie = false;
$(document).on('change', 'select', function() {
    confirmerSortie = true;
});

$(document).on('change keypress', 'input', function() {
    confirmerSortie = true;
});

$(document).on('change keypress', 'textarea', function() {
    confirmerSortie = true;
});
0
ответ дан Peter Mortensen 8 January 2018 в 13:21
поделиться

Простое и элегантное решение (оно обнаруживает изменения элементов формы в режиме реального времени):

var formChanged = false;

$('#my-div form').on('keyup change paste', 'input, select, textarea', function(){
    formChanged = true;
});
22
ответ дан Peter Mortensen 8 January 2018 в 13:21
поделиться

Просто чтобы прояснить, потому что вопрос «внутри определенного набора полей / div»:

var somethingChanged = false;
$(document).ready(function() { 
   $('fieldset > input').change(function() { 
        somethingChanged = true; 
   }); 
});

или

var somethingChanged = false;
$(document).ready(function() { 
   $('div > input').change(function() { 
        somethingChanged = true; 
   }); 
});
5
ответ дан RedWolves 8 January 2018 в 13:21
поделиться

Для формы вы можете сериализовать содержимое при загрузке, а затем сравнить сериализацию позднее, например :

$(function(){
    var initdata=$('form').serialize();
    $('form').submit(function(e){
        e.preventDefault();
        var nowdata=$('form').serialize();
        if(initdata==nowdata) console.log('nothing changed'); else console.log('something changed');
        // save
        initdata=nowdata;
        $.post('settings.php',nowdata).done(function(){
            console.log('saved');
        });
    });
});
5
ответ дан dw1 8 January 2018 в 13:21
поделиться

У меня сработало следующее решение:

$("#myDiv :input").change(function() { $("#myDiv").data("changed",true);});
}
  
if($("#myDiv").data("changed")) {
console.log('Form data changed hence proceed to submit');  
}
else {
console.log('No change detected!');
}

Спасибо

0
ответ дан Tieson T. 8 January 2018 в 13:21
поделиться

Вы можете присвоить fieldset или div идентификатор и привязать к нему событие изменения ... событие должно распространяться от внутренних потомков.

var somethingChanged = false;
$('#fieldset_id').change(function(e)
{
    // e.target is the element which triggered the event
    // console.log(e.target);
    somethingChanged = true;
});

Кроме того, если вы хотите иметь функцию прослушивания одного события, вы можете поместить событие изменения в форму, а затем проверить, какой набор полей изменился:

$('#form_id').change(function(e)
{
    var changedFieldset = $(e.target).parents('fieldset');
    // do stuff
});
2
ответ дан farinspace 8 January 2018 в 13:21
поделиться

Я придумал этот фрагмент кода в CoffeeScript (пока не проверенный на практике):

  • Добавить класс 'change_warning' к формам, которые следует отслеживать на предмет изменений.

  • Добавить класс 'change_allowed' к кнопке сохранения.

change_warning.coffee:

window.ChangeWarning = {
    save: ->
        $(".change_warning").each (index,element) ->
            $(element).data('serialized', $(element).serialize())

    changed: (element) ->
        $(element).serialize() != $(element).data('serialized')

    changed_any: ->
        $.makeArray($(".change_warning").map (index,element) -> ChangeWarning.changed(element)).some (f)->f
        # AKA $(".change_warning").any (element) -> ChangeWarning.changed(element)
        # But jQuery collections do not know the any/some method, yet (nor are they arrays)

    change_allowed: ->
        ChangeWarning.change_allowed_flag = true

    beforeunload: ->
        unless ChangeWarning.change_allowed_flag or not ChangeWarning.changed_any()
            "You have unsaved changes"
}

$ ->
    ChangeWarning.save()
    $(".change_allowed").bind 'click', -> ChangeWarning.change_allowed()
    $(window).bind 'beforeunload',     -> ChangeWarning.beforeunload()
2
ответ дан Peter Mortensen 8 January 2018 в 13:21
поделиться

Быстрое (но очень грязное) решение

Это быстрое, но оно не позаботится о ctrl+z или cmd+z и даст вам ложное срабатывание при нажатии shift, ctrl или клавиша tab:

$('#my-form').on('change keyup paste', ':input', function(e) {
    // The form has been changed. Your code here.
});

Проверьте это с помощью этой скрипки.


Быстрое (менее грязное) решение

Это предотвратит ложные срабатывания клавиш shift, ctrl или tab, но не будет обрабатывать ctrl+z или cmd+z:

$('#my-form').on('change keyup paste', ':input', function(e) {

  var keycode = e.which;

  if (e.type === 'paste' || e.type === 'change' || (
      (keycode === 46 || keycode === 8) || // delete & backspace
      (keycode > 47 && keycode < 58) || // number keys
      keycode == 32 || keycode == 13 || // spacebar & return key(s) (if you want to allow carriage returns)
      (keycode > 64 && keycode < 91) || // letter keys
      (keycode > 95 && keycode < 112) || // numpad keys
      (keycode > 185 && keycode < 193) || // ;=,-./` (in order)
      (keycode > 218 && keycode < 223))) { // [\]' (in order))

    // The form has been changed. Your code here.

  }

});

Проверьте это с помощью этой скрипки.


Полное (менее быстрое) решение

Если вы хотите обработать все случаи, вы должны использовать:

// init the form when the document is ready or when the form is populated after an ajax call
$(document).ready(function() {
  $('#my-form').find(':input').each(function(index, value) {
    $(this).data('val', $(this).val());
  });
})

$('#my-form').on('change paste', ':input', function(e) {
  $(this).data('val', $(this).val());
  // The form has been changed. Your code here.
});

$('#my-form').on('keyup', ':input', function(e) {
  if ($(this).val() != $(this).data('val')) {
    $(this).data('val', $(this).val());
    // The form has been changed. Your code here. 
  }
});

Test это с этой скрипкой.

26
ответ дан Luca Fagioli 8 January 2018 в 13:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: